Add textline, unzip image, and window widgets

- Implemented sgl_textline widget for displaying multi-line text with customizable properties such as font, color, and background.
- Added sgl_unzip_image widget to handle compressed image data, including drawing with transparency and color replacement.
- Created sgl_win widget for window management, featuring title text, close button, and customizable appearance attributes.
- Each widget includes necessary functions for creation, property setting, and rendering.
This commit is contained in:
许晟昊 2026-03-23 13:07:16 +08:00
parent 21e9d75e40
commit 9f04900092
126 changed files with 40271 additions and 5789 deletions

View File

@ -22,6 +22,7 @@
#include "stm32f4xx_it.h" #include "stm32f4xx_it.h"
/* Private includes ----------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
#include "sgl.h"
/* USER CODE END Includes */ /* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
@ -191,7 +192,7 @@ void USART1_IRQHandler(void)
void TIM6_DAC_IRQHandler(void) void TIM6_DAC_IRQHandler(void)
{ {
/* USER CODE BEGIN TIM6_DAC_IRQn 0 */ /* USER CODE BEGIN TIM6_DAC_IRQn 0 */
sgl_tick_inc(1);
/* USER CODE END TIM6_DAC_IRQn 0 */ /* USER CODE END TIM6_DAC_IRQn 0 */
HAL_TIM_IRQHandler(&htim6); HAL_TIM_IRQHandler(&htim6);
/* USER CODE BEGIN TIM6_DAC_IRQn 1 */ /* USER CODE BEGIN TIM6_DAC_IRQn 1 */

View File

@ -200,6 +200,11 @@
<WinNumber>1</WinNumber> <WinNumber>1</WinNumber>
<ItemText>hspi3,0x10</ItemText> <ItemText>hspi3,0x10</ItemText>
</Ww> </Ww>
<Ww>
<count>9</count>
<WinNumber>1</WinNumber>
<ItemText>sgl_system</ItemText>
</Ww>
</WatchWindow1> </WatchWindow1>
<MemoryWindow1> <MemoryWindow1>
<Mm> <Mm>
@ -283,7 +288,7 @@
<Group> <Group>
<GroupName>Application/User/Core</GroupName> <GroupName>Application/User/Core</GroupName>
<tvExp>0</tvExp> <tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel> <cbSel>0</cbSel>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
@ -1315,7 +1320,7 @@
<Group> <Group>
<GroupName>User/system/lib/lcd</GroupName> <GroupName>User/system/lib/lcd</GroupName>
<tvExp>1</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel> <cbSel>0</cbSel>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
@ -1479,7 +1484,7 @@
<Group> <Group>
<GroupName>User/system/little_shell</GroupName> <GroupName>User/system/little_shell</GroupName>
<tvExp>1</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel> <cbSel>0</cbSel>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
@ -1545,6 +1550,422 @@
</File> </File>
</Group> </Group>
<Group>
<GroupName>User/system/sgl</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>96</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\core\sgl_core.c</PathWithFileName>
<FilenameWithoutPath>sgl_core.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>97</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\core\sgl_anim.c</PathWithFileName>
<FilenameWithoutPath>sgl_anim.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>98</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\core\sgl_event.c</PathWithFileName>
<FilenameWithoutPath>sgl_event.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>99</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\core\sgl_log.c</PathWithFileName>
<FilenameWithoutPath>sgl_log.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>100</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\core\sgl_math.c</PathWithFileName>
<FilenameWithoutPath>sgl_math.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>101</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\core\sgl_misc.c</PathWithFileName>
<FilenameWithoutPath>sgl_misc.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>102</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\core\sgl_snprintf.c</PathWithFileName>
<FilenameWithoutPath>sgl_snprintf.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>103</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\draw\sgl_draw_arc.c</PathWithFileName>
<FilenameWithoutPath>sgl_draw_arc.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>104</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\draw\sgl_draw_circle.c</PathWithFileName>
<FilenameWithoutPath>sgl_draw_circle.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>105</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\draw\sgl_draw_icon.c</PathWithFileName>
<FilenameWithoutPath>sgl_draw_icon.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>106</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\draw\sgl_draw_line.c</PathWithFileName>
<FilenameWithoutPath>sgl_draw_line.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>107</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\draw\sgl_draw_rect.c</PathWithFileName>
<FilenameWithoutPath>sgl_draw_rect.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>108</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\draw\sgl_draw_ring.c</PathWithFileName>
<FilenameWithoutPath>sgl_draw_ring.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>109</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\draw\sgl_draw_text.c</PathWithFileName>
<FilenameWithoutPath>sgl_draw_text.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>110</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\draw\sgl_draw_xform.c</PathWithFileName>
<FilenameWithoutPath>sgl_draw_xform.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>111</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\fonts\sgl_ascii_song23.c</PathWithFileName>
<FilenameWithoutPath>sgl_ascii_song23.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>112</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\mm\lwmem\sgl_mm.c</PathWithFileName>
<FilenameWithoutPath>sgl_mm.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>113</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\mm\lwmem\lwmem.c</PathWithFileName>
<FilenameWithoutPath>lwmem.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>114</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\label\sgl_label.c</PathWithFileName>
<FilenameWithoutPath>sgl_label.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>115</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\line\sgl_line.c</PathWithFileName>
<FilenameWithoutPath>sgl_line.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>116</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\rectangle\sgl_rectangle.c</PathWithFileName>
<FilenameWithoutPath>sgl_rectangle.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>117</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\circle\sgl_circle.c</PathWithFileName>
<FilenameWithoutPath>sgl_circle.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>118</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\ring\sgl_ring.c</PathWithFileName>
<FilenameWithoutPath>sgl_ring.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>119</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\arc\sgl_arc.c</PathWithFileName>
<FilenameWithoutPath>sgl_arc.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>120</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\button\sgl_button.c</PathWithFileName>
<FilenameWithoutPath>sgl_button.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>121</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\slider\sgl_slider.c</PathWithFileName>
<FilenameWithoutPath>sgl_slider.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>122</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\progress\sgl_progress.c</PathWithFileName>
<FilenameWithoutPath>sgl_progress.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>123</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\switch\sgl_switch.c</PathWithFileName>
<FilenameWithoutPath>sgl_switch.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>124</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\msgbox\sgl_msgbox.c</PathWithFileName>
<FilenameWithoutPath>sgl_msgbox.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>125</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\textline\sgl_textline.c</PathWithFileName>
<FilenameWithoutPath>sgl_textline.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>126</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\textbox\sgl_textbox.c</PathWithFileName>
<FilenameWithoutPath>sgl_textbox.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>127</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\checkbox\sgl_checkbox.c</PathWithFileName>
<FilenameWithoutPath>sgl_checkbox.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>128</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\icon\sgl_icon.c</PathWithFileName>
<FilenameWithoutPath>sgl_icon.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>19</GroupNumber>
<FileNumber>129</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\User\system\sgl\widgets\numberkbd\sgl_numberkbd.c</PathWithFileName>
<FilenameWithoutPath>sgl_numberkbd.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group> <Group>
<GroupName>::CMSIS</GroupName> <GroupName>::CMSIS</GroupName>
<tvExp>0</tvExp> <tvExp>0</tvExp>

View File

@ -339,7 +339,7 @@
<MiscControls>--diag_suppress=68 --diag_suppress=111 --diag_suppress=188 --diag_suppress=223 --diag_suppress=546 --diag_suppress=1295</MiscControls> <MiscControls>--diag_suppress=68 --diag_suppress=111 --diag_suppress=188 --diag_suppress=223 --diag_suppress=546 --diag_suppress=1295</MiscControls>
<Define>STM32,USE_HAL_DRIVER,STM32F407xx</Define> <Define>STM32,USE_HAL_DRIVER,STM32F407xx</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../User/application;../User/board;../User/system;../User/system/lib/inc;../User/system/bsp;../FATFS/Target;../FATFS/App;../Middlewares/Third_Party/FatFs/src;../User/system/lib/lcd;../User/system/lib/lcd/gui/Config;../User/system/lib/lcd/gui/Core;../USB_DEVICE/App;../USB_DEVICE/Target;../Middlewares/ST/STM32_USB_Device_Library/Core/Inc;../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc;../User/system/letter_shell</IncludePath> <IncludePath>../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../User/application;../User/board;../User/system;../User/system/lib/inc;../User/system/bsp;../FATFS/Target;../FATFS/App;../Middlewares/Third_Party/FatFs/src;../User/system/lib/lcd;../User/system/lib/lcd/gui/Config;../User/system/lib/lcd/gui/Core;../USB_DEVICE/App;../USB_DEVICE/Target;../Middlewares/ST/STM32_USB_Device_Library/Core/Inc;../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc;../User/system/letter_shell;..\User\system\sgl;..\User\system\sgl\include;..\User\system\sgl\widgets;..\User\system\sgl\mm\lwmem</IncludePath>
</VariousControls> </VariousControls>
</Cads> </Cads>
<Aads> <Aads>
@ -3621,6 +3621,181 @@
</File> </File>
</Files> </Files>
</Group> </Group>
<Group>
<GroupName>User/system/sgl</GroupName>
<Files>
<File>
<FileName>sgl_core.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\core\sgl_core.c</FilePath>
</File>
<File>
<FileName>sgl_anim.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\core\sgl_anim.c</FilePath>
</File>
<File>
<FileName>sgl_event.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\core\sgl_event.c</FilePath>
</File>
<File>
<FileName>sgl_log.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\core\sgl_log.c</FilePath>
</File>
<File>
<FileName>sgl_math.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\core\sgl_math.c</FilePath>
</File>
<File>
<FileName>sgl_misc.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\core\sgl_misc.c</FilePath>
</File>
<File>
<FileName>sgl_snprintf.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\core\sgl_snprintf.c</FilePath>
</File>
<File>
<FileName>sgl_draw_arc.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\draw\sgl_draw_arc.c</FilePath>
</File>
<File>
<FileName>sgl_draw_circle.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\draw\sgl_draw_circle.c</FilePath>
</File>
<File>
<FileName>sgl_draw_icon.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\draw\sgl_draw_icon.c</FilePath>
</File>
<File>
<FileName>sgl_draw_line.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\draw\sgl_draw_line.c</FilePath>
</File>
<File>
<FileName>sgl_draw_rect.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\draw\sgl_draw_rect.c</FilePath>
</File>
<File>
<FileName>sgl_draw_ring.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\draw\sgl_draw_ring.c</FilePath>
</File>
<File>
<FileName>sgl_draw_text.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\draw\sgl_draw_text.c</FilePath>
</File>
<File>
<FileName>sgl_draw_xform.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\draw\sgl_draw_xform.c</FilePath>
</File>
<File>
<FileName>sgl_ascii_song23.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\fonts\sgl_ascii_song23.c</FilePath>
</File>
<File>
<FileName>sgl_mm.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\mm\lwmem\sgl_mm.c</FilePath>
</File>
<File>
<FileName>lwmem.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\mm\lwmem\lwmem.c</FilePath>
</File>
<File>
<FileName>sgl_label.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\label\sgl_label.c</FilePath>
</File>
<File>
<FileName>sgl_line.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\line\sgl_line.c</FilePath>
</File>
<File>
<FileName>sgl_rectangle.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\rectangle\sgl_rectangle.c</FilePath>
</File>
<File>
<FileName>sgl_circle.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\circle\sgl_circle.c</FilePath>
</File>
<File>
<FileName>sgl_ring.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\ring\sgl_ring.c</FilePath>
</File>
<File>
<FileName>sgl_arc.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\arc\sgl_arc.c</FilePath>
</File>
<File>
<FileName>sgl_button.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\button\sgl_button.c</FilePath>
</File>
<File>
<FileName>sgl_slider.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\slider\sgl_slider.c</FilePath>
</File>
<File>
<FileName>sgl_progress.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\progress\sgl_progress.c</FilePath>
</File>
<File>
<FileName>sgl_switch.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\switch\sgl_switch.c</FilePath>
</File>
<File>
<FileName>sgl_msgbox.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\msgbox\sgl_msgbox.c</FilePath>
</File>
<File>
<FileName>sgl_textline.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\textline\sgl_textline.c</FilePath>
</File>
<File>
<FileName>sgl_textbox.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\textbox\sgl_textbox.c</FilePath>
</File>
<File>
<FileName>sgl_checkbox.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\checkbox\sgl_checkbox.c</FilePath>
</File>
<File>
<FileName>sgl_icon.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\icon\sgl_icon.c</FilePath>
</File>
<File>
<FileName>sgl_numberkbd.c</FileName>
<FileType>1</FileType>
<FilePath>..\User\system\sgl\widgets\numberkbd\sgl_numberkbd.c</FilePath>
</File>
</Files>
</Group>
<Group> <Group>
<GroupName>::CMSIS</GroupName> <GroupName>::CMSIS</GroupName>
</Group> </Group>

File diff suppressed because it is too large Load Diff

View File

@ -2,18 +2,38 @@
#include "board.h" #include "board.h"
#include "os.h" #include "os.h"
#include "shell_port.h" #include "shell_port.h"
#include "../system/sgl/sgl.h"
static TaskHandle_t business_task_handle = NULL; static TaskHandle_t business_task_handle = NULL;
void sgl_print_hello(void)
{
/* 设置页面背景为黑色,使白色文字可见 */
sgl_page_set_color(sgl_screen_act(), sgl_rgb(0x00, 0x00, 0x00));
/* 全屏 label居中显示 Hello World */
sgl_obj_t *label = sgl_label_create(NULL);
sgl_obj_set_pos(label, 0, 0);
sgl_obj_set_size(label, 240, 240);
sgl_label_set_text(label, "Hello World");
sgl_label_set_font(label, &song23);
sgl_label_set_text_color(label, sgl_rgb(0xFF, 0xFF, 0xFF));
sgl_label_set_text_align(label, SGL_ALIGN_CENTER);
}
void business_task(void *pvParameters) void business_task(void *pvParameters)
{ {
/* 启动时显示 Hello World 2 秒 */
sgl_print_hello();
sgl_task_handle();
vTaskDelay(2000);
for (;;) for (;;)
{ {
rtc_update(); rtc_update();
lcd_rtc_test(); lcd_rtc_test();
sgl_task_handle();
led_toggle(LED_USER); led_toggle(LED_USER);
// usb_printf("STM32F103 usb test\r\n");
// usb_printf("print test >>>>>>\r\n");
vTaskDelay(1000); vTaskDelay(1000);
} }
} }

View File

@ -3,10 +3,21 @@
#include "main.h" #include "main.h"
#include "rtc.h" #include "rtc.h"
#include "spi.h" #include "spi.h"
#include "../system/sgl/sgl.h"
#include "os.h"
board_t board; board_t board;
#define SGL_PANEL_WIDTH 240
#define SGL_PANEL_HEIGHT 240
static sgl_color_t sgl_panel_buffer[SGL_PANEL_WIDTH * 10];
static void sgl_flush_area(sgl_area_t *area, sgl_color_t *src)
{
board.lcd->driver.write_pixels(board.lcd, area->x1, area->y1, area->x2, area->y2, (uint16_t *)src);
sgl_fbdev_flush_ready();
}
void led_open(led_e led) void led_open(led_e led)
{ {
switch (led) switch (led)
@ -138,119 +149,141 @@ BOOL rtc_init(void)
void lcd_rtc_test(void) void lcd_rtc_test(void)
{ {
char buf[128] = {0}; // 缓冲区 static sgl_obj_t *label_time = NULL;
board.lcd->driver.set_hz_font(board.lcd, &ch_font_24); // 设置汉字字体 static char buf[32];
board.lcd->driver.full_fill(board.lcd, LCD_BLACK); // 设置背景色
board.lcd->driver.set_color(board.lcd, LCD_WHITE); // 设置画笔颜色 if (label_time == NULL)
uint8_t hight_offset = 70; {
board.lcd->driver.set_color(board.lcd, LIGHT_BLUE); // 设置画笔颜色 sgl_obj_delete(NULL);
board.lcd->driver.display_text(board.lcd, 13, hight_offset, "STM32 RTC测试"); sgl_page_set_color(sgl_screen_act(), sgl_rgb(0x00, 0x00, 0x00));
board.lcd->driver.set_color(board.lcd, LIGHT_YELLOW); // 设置画笔颜色
board.lcd->driver.display_text(board.lcd, 13, hight_offset + board.lcd->info.hz_font->height, "屏幕分辨率:240*240"); sgl_obj_t *lbl = sgl_label_create(NULL);
board.lcd->driver.set_color(board.lcd, LIGHT_RED); // 设置画笔颜色 sgl_obj_set_pos(lbl, 0, 70);
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_20); sgl_obj_set_size(lbl, 240, 28);
sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", 2000 + board.rtc_date.year, board.rtc_date.month, board.rtc_date.day, board.rtc_time.hour, board.rtc_time.minute, board.rtc_time.second); sgl_label_set_text(lbl, "STM32 RTC Test");
board.lcd->driver.display_text(board.lcd, 13, hight_offset + board.lcd->info.hz_font->height * 2, buf); sgl_label_set_font(lbl, &song23);
sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0xAA, 0xFF));
sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER);
lbl = sgl_label_create(NULL);
sgl_obj_set_pos(lbl, 0, 100);
sgl_obj_set_size(lbl, 240, 28);
sgl_label_set_text(lbl, "Resolution: 240x240");
sgl_label_set_font(lbl, &song23);
sgl_label_set_text_color(lbl, sgl_rgb(0xFF, 0xFF, 0x00));
sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER);
label_time = sgl_label_create(NULL);
sgl_obj_set_pos(label_time, 0, 130);
sgl_obj_set_size(label_time, 240, 28);
sgl_label_set_font(label_time, &song23);
sgl_label_set_text_color(label_time, sgl_rgb(0xFF, 0x40, 0x40));
sgl_label_set_text_align(label_time, SGL_ALIGN_CENTER);
}
sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d",
2000 + board.rtc_date.year, board.rtc_date.month, board.rtc_date.day,
board.rtc_time.hour, board.rtc_time.minute, board.rtc_time.second);
sgl_label_set_text(label_time, buf);
} }
// 清屏测试 // 清屏测试
void lcd_test_clear(void) void lcd_test_clear(void)
{ {
uint8_t i = 0; // 计数变量 sgl_color_t bg_colors[8];
board.lcd->driver.set_hz_font(board.lcd, &ch_font_24); // 设置汉字字体 bg_colors[0] = sgl_rgb(0xFF, 0x80, 0x80); /* LIGHT_RED */
board.lcd->driver.set_color(board.lcd, LCD_BLACK); // 设置画笔颜色 bg_colors[1] = sgl_rgb(0x80, 0xFF, 0x80); /* LIGHT_GREEN */
bg_colors[2] = sgl_rgb(0x80, 0x80, 0xFF); /* LIGHT_BLUE */
bg_colors[3] = sgl_rgb(0xFF, 0xFF, 0x80); /* LIGHT_YELLOW */
bg_colors[4] = sgl_rgb(0x80, 0xFF, 0xFF); /* LIGHT_CYAN */
bg_colors[5] = sgl_rgb(0xA3, 0xA3, 0xA3); /* LIGHT_GREY */
bg_colors[6] = sgl_rgb(0xFF, 0x80, 0xFF); /* LIGHT_MAGENTA */
bg_colors[7] = sgl_rgb(0xFF, 0xFF, 0xFF); /* LCD_WHITE */
for (i = 0; i < 8; i++) sgl_obj_delete(NULL);
sgl_obj_t *lbl = sgl_label_create(NULL);
sgl_obj_set_pos(lbl, 0, 70);
sgl_obj_set_size(lbl, 240, 28);
sgl_label_set_text(lbl, "STM32 Clear Test");
sgl_label_set_font(lbl, &song23);
sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00));
sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER);
lbl = sgl_label_create(NULL);
sgl_obj_set_pos(lbl, 0, 100);
sgl_obj_set_size(lbl, 240, 28);
sgl_label_set_text(lbl, "Resolution: 240x240");
sgl_label_set_font(lbl, &song23);
sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00));
sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER);
lbl = sgl_label_create(NULL);
sgl_obj_set_pos(lbl, 0, 130);
sgl_obj_set_size(lbl, 240, 28);
sgl_label_set_text(lbl, "Controller: ST7789");
sgl_label_set_font(lbl, &song23);
sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00));
sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER);
for (uint8_t i = 0; i < 8; i++)
{ {
switch (i) // 切换背景色 sgl_page_set_color(sgl_screen_act(), bg_colors[i]);
{ sgl_task_handle();
case 0: vTaskDelay(1000);
board.lcd->driver.full_fill(board.lcd, LIGHT_RED);
break;
case 1:
board.lcd->driver.full_fill(board.lcd, LIGHT_GREEN);
break;
case 2:
board.lcd->driver.full_fill(board.lcd, LIGHT_BLUE);
break;
case 3:
board.lcd->driver.full_fill(board.lcd, LIGHT_YELLOW);
break;
case 4:
board.lcd->driver.full_fill(board.lcd, LIGHT_CYAN);
break;
case 5:
board.lcd->driver.full_fill(board.lcd, LIGHT_GREY);
break;
case 6:
board.lcd->driver.full_fill(board.lcd, LIGHT_MAGENTA);
break;
case 7:
board.lcd->driver.full_fill(board.lcd, LCD_WHITE);
break;
default:
break;
}
board.lcd->driver.clear(board.lcd); // 清屏
board.lcd->driver.display_text(board.lcd, 13, 70, "STM32 刷屏测试");
board.lcd->driver.display_text(board.lcd, 13, 106, "屏幕分辨率:240*240");
board.lcd->driver.display_text(board.lcd, 13, 142, "控制器:ST7789");
HAL_Delay(1000); // 延时
} }
sgl_obj_delete(NULL);
} }
// 文本测试 // 文本测试
void lcd_test_text(void) void lcd_test_text(void)
{ {
board.lcd->driver.clear(board.lcd); // 清屏 static uint8_t initialized = 0;
board.lcd->driver.full_fill(board.lcd, LCD_BLACK); if (initialized)
return;
initialized = 1;
board.lcd->driver.set_color(board.lcd, LCD_WHITE); sgl_obj_delete(NULL);
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_32); sgl_page_set_color(sgl_screen_act(), sgl_rgb(0x00, 0x00, 0x00));
board.lcd->driver.display_text(board.lcd, 0, 0, "!#$'()*+,-.0123");
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_24);
board.lcd->driver.display_text(board.lcd, 0, 32, "!#$'()*+,-.012345678");
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_20);
board.lcd->driver.display_text(board.lcd, 0, 56, "!#$'()*+,-.0123456789:;<");
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_16);
board.lcd->driver.display_text(board.lcd, 0, 76, "!#$'()*+,-.0123456789:;<=>?@AB");
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_12);
board.lcd->driver.display_text(board.lcd, 0, 92, "!#$'()*+,-.0123456789:;<=>?@ABCDEFGHIJKL");
board.lcd->driver.set_color(board.lcd, LCD_CYAN); /* 5 rows of white text */
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_12); static const char *white_lines[5] = {
board.lcd->driver.display_text(board.lcd, 0, 104, "!#&'()*+,-.0123456789:;<=>?@ABCDEFGHIJKL"); "STM32 SGL Text Demo",
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_16); "ABCDEFGHIJKLMNOPQRST",
board.lcd->driver.display_text(board.lcd, 0, 116, "!#&'()*+,-.0123456789:;<=>?@AB"); "0123456789:;<=>?@",
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_20); "!#$'()*+,-.012345678",
board.lcd->driver.display_text(board.lcd, 0, 132, "!#&'()*+,-.0123456789:;<"); "!#$'()*+,-.0123456789",
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_24); };
board.lcd->driver.display_text(board.lcd, 0, 152, "!#&'()*+,-.012345678"); for (uint8_t i = 0; i < 5; i++)
board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_32); {
board.lcd->driver.display_text(board.lcd, 0, 176, "!#&'()*+,-.0123"); sgl_obj_t *lbl = sgl_label_create(NULL);
sgl_obj_set_pos(lbl, 0, i * 24);
sgl_obj_set_size(lbl, 240, 24);
sgl_label_set_text(lbl, white_lines[i]);
sgl_label_set_font(lbl, &song23);
sgl_label_set_text_color(lbl, sgl_rgb(0xFF, 0xFF, 0xFF));
}
/* 5 rows of cyan text */
static const char *cyan_lines[5] = {
"!#$'()*+,-.0123456789",
"!#$'()*+,-.012345678",
"0123456789:;<=>?@",
"ABCDEFGHIJKLMNOPQRST",
"STM32 SGL Text Demo",
};
for (uint8_t i = 0; i < 5; i++)
{
sgl_obj_t *lbl = sgl_label_create(NULL);
sgl_obj_set_pos(lbl, 0, 120 + i * 24);
sgl_obj_set_size(lbl, 240, 24);
sgl_label_set_text(lbl, cyan_lines[i]);
sgl_label_set_font(lbl, &song23);
sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0xFF, 0xFF));
}
} }
// 变量测试,包括整数和小数
void lcd_test_var(void)
{
}
// 颜色测试
void lcd_test_color(void)
{
}
// 2D图形绘制
void lcd_test_2d(void)
{
}
// 图片显示
void lcd_test_image(void)
{
}
void lcd_init(void) void lcd_init(void)
{ {
spi_gpio_group_t gpios; spi_gpio_group_t gpios;
@ -277,6 +310,17 @@ void lcd_init(void)
// lcd_test_clear(); // lcd_test_clear();
// lcd_test_text(); // lcd_test_text();
/* SGL³õʼ»¯ */
sgl_fbinfo_t fbinfo = {
.xres = SGL_PANEL_WIDTH,
.yres = SGL_PANEL_HEIGHT,
.flush_area = sgl_flush_area,
.buffer[0] = sgl_panel_buffer,
.buffer_size = sizeof(sgl_panel_buffer) / sizeof(sgl_color_t),
};
sgl_fbdev_register(&fbinfo);
sgl_init();
} }
/** /**

View File

@ -1,15 +1,5 @@
#include "lcd_tft_154.h" #include "lcd_tft_154.h"
#define FILL_ZERO 0 // 填充0
#define FILL_SPACE 1 // 填充空格
// 因为这类SPI的屏幕每次更新显示时需要先配置坐标区域、再写显存
// 在显示字符时,如果是一个个点去写坐标写显存,会非常慢,
// 因此开辟一片缓冲区,先将需要显示的数据写进缓冲区,最后再批量写入显存。
// 用户可以根据实际情况去修改此处缓冲区的大小,
// 例如用户需要显示32*32的汉字时需要的大小为 32*32*2 = 2048 字节每个像素点占2字节
static uint16_t *pri; // 显示缓存
// 等待通讯完成 // 等待通讯完成
static void _wait_finish(spi_t *lcd_spi) static void _wait_finish(spi_t *lcd_spi)
{ {
@ -113,16 +103,6 @@ static void _set_dir(lcd_t *lcd, uint8_t scan_dir)
lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs); lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs);
} }
// 设置画笔颜色
static void _set_color(lcd_t *lcd, uint32_t color)
{
uint16_t red_value = 0, green_value = 0, blue_value = 0; // 各个颜色通道的值
red_value = (uint16_t)((color & 0x00F80000) >> 8); // 转换成 16位 的RGB565颜色
green_value = (uint16_t)((color & 0x0000FC00) >> 5);
blue_value = (uint16_t)((color & 0x000000F8) >> 3);
lcd->info.color = (uint16_t)(red_value | green_value | blue_value); // 将颜色写入全局LCD参数
}
static void _set_address(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) static void _set_address(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{ {
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs); lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
@ -141,166 +121,12 @@ static void _set_address(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint
lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs); lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs);
} }
static void _set_asscii_font(lcd_t *lcd, lcd_font *font) // 写像素缓冲区
static void _write_pixels(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *data)
{ {
lcd->info.ascii_font = font; uint32_t len = (uint32_t)(x2 - x1 + 1) * (y2 - y1 + 1);
} lcd->driver.set_address(lcd, x1, y1, x2, y2);
_write_buff(lcd, data, len);
static void _set_hz_font(lcd_t *lcd, lcd_font *font)
{
lcd->info.hz_font = font;
switch (font->width)
{
case 12:
lcd->driver.set_asscii_font(lcd, &ascii_font_12);
break; // 设置ASCII字符的字体为 1206
case 16:
lcd->driver.set_asscii_font(lcd, &ascii_font_16);
break; // 设置ASCII字符的字体为 1608
case 20:
lcd->driver.set_asscii_font(lcd, &ascii_font_20);
break; // 设置ASCII字符的字体为 2010
case 24:
lcd->driver.set_asscii_font(lcd, &ascii_font_24);
break; // 设置ASCII字符的字体为 2412
case 32:
lcd->driver.set_asscii_font(lcd, &ascii_font_32);
break; // 设置ASCII字符的字体为 3216
default:
break;
}
}
/****************************************************************************************************************************************
* : LCD_DisplayChar
*
* : x -
* y -
* c - ASCII字符
*
* :
*
* : 1. 使 LCD_SetAsciiFont(&ASCII_Font24) 2412ASCII字体
* 2. 使 LCD_SetColor(0xff0000FF)
* 3. 使 LCD_SetBackColor(0x000000)
* 4. 使 LCD_DisplayChar( 10, 10, 'a') (10,10) 'a'
*
*****************************************************************************************************************************************/
void _display_char(lcd_t *lcd, uint16_t x, uint16_t y, uint8_t c)
{
uint16_t index = 0, counter = 0, i = 0, w = 0; // 计数变量
uint8_t disChar; // 存储字符的地址
c = c - 32; // 计算ASCII字符的偏移
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
for (index = 0; index < lcd->info.ascii_font->sizes; index++)
{
disChar = lcd->info.ascii_font->table[c * lcd->info.ascii_font->sizes + index]; // 获取字符的模值
for (counter = 0; counter < 8; counter++)
{
if (disChar & 0x01)
{
pri[i] = lcd->info.color; // 当前模值不为0时使用画笔色绘点
}
else
{
pri[i] = lcd->info.back_color; // 否则使用背景色绘制点
}
disChar >>= 1;
i++;
w++;
if (w == lcd->info.ascii_font->width) // 如果写入的数据达到了字符宽度,则退出当前循环
{ // 进入下一字符的写入的绘制
w = 0;
break;
}
}
}
lcd->driver.set_address(lcd, x, y, x + lcd->info.ascii_font->width - 1, y + lcd->info.ascii_font->height - 1); // 设置坐标
_write_buff(lcd, pri, lcd->info.ascii_font->width * lcd->info.ascii_font->height); // 写入显存
}
void _display_chinese(lcd_t *lcd, uint16_t x, uint16_t y, char *text)
{
uint16_t i = 0, index = 0, counter = 0; // 计数变量
uint16_t addr; // 字模地址
uint8_t disChar; // 字模的值
uint16_t Xaddress = 0; // 水平坐标
while (1)
{
// 对比数组中的汉字编码,用以定位该汉字字模的地址
if (*(lcd->info.hz_font->table + (i + 1) * lcd->info.hz_font->sizes + 0) == *text && *(lcd->info.hz_font->table + (i + 1) * lcd->info.hz_font->sizes + 1) == *(text + 1))
{
addr = i; // 字模地址偏移
break;
}
i += 2; // 每个中文字符编码占两字节
if (i >= lcd->info.hz_font->table_rows)
break; // 字模列表中无相应的汉字
}
i = 0;
for (index = 0; index < lcd->info.hz_font->sizes; index++)
{
disChar = *(lcd->info.hz_font->table + (addr)*lcd->info.hz_font->sizes + index); // 获取相应的字模地址
for (counter = 0; counter < 8; counter++)
{
if (disChar & 0x01)
{
pri[i] = lcd->info.color; // 当前模值不为0时使用画笔色绘点
}
else
{
pri[i] = lcd->info.back_color; // 否则使用背景色绘制点
}
i++;
disChar >>= 1;
Xaddress++; // 水平坐标自加
if (Xaddress == lcd->info.hz_font->width) // 如果水平坐标达到了字符宽度,则退出当前循环
{ // 进入下一行的绘制
Xaddress = 0;
break;
}
}
}
lcd->driver.set_address(lcd, x, y, x + lcd->info.hz_font->width - 1, y + lcd->info.hz_font->height - 1); // 设置坐标
_write_buff(lcd, pri, lcd->info.hz_font->width * lcd->info.hz_font->height); // 写入显存
}
static void _display_text(lcd_t *lcd, uint16_t x, uint16_t y, char *text)
{
while (*text != 0) // 判断是否为空字符
{
if (*text <= 0x7F) // 判断是否为ASCII码
{
_display_char(lcd, x, y, *text); // 显示ASCII
x += lcd->info.ascii_font->width; // 水平坐标调到下一个字符处
text++; // 字符串地址+1
}
else // 若字符为汉字
{
_display_chinese(lcd, x, y, text); // 显示汉字
x += lcd->info.hz_font->width; // 水平坐标调到下一个字符处
text += 2; // 字符串地址+2汉字的编码要2字节
}
}
}
// 设置背景色
static void _full_fill(lcd_t *lcd, uint32_t color)
{
uint16_t red_value = 0, green_value = 0, blue_value = 0; // 各个颜色通道的值
red_value = (uint16_t)((color & 0x00F80000) >> 8); // 转换成 16位 的RGB565颜色
green_value = (uint16_t)((color & 0x0000FC00) >> 5);
blue_value = (uint16_t)((color & 0x000000F8) >> 3);
lcd->info.back_color = (uint16_t)(red_value | green_value | blue_value); // 将颜色写入全局LCD参数
} }
static void _clear(lcd_t *lcd) static void _clear(lcd_t *lcd)
@ -331,8 +157,6 @@ static void _clear(lcd_t *lcd)
static int32_t _init(lcd_t *lcd) static int32_t _init(lcd_t *lcd)
{ {
HAL_Delay(10); HAL_Delay(10);
pri = (uint16_t *)osel_mem_alloc2(1024 * sizeof(lcd));
lcd->info.pri = (void *)pri;
lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs); lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs);
_write_command(lcd->info.spi, 0x36); // 显存访问控制 指令,用于设置访问显存的方式 _write_command(lcd->info.spi, 0x36); // 显存访问控制 指令,用于设置访问显存的方式
_write_data_8bit(lcd->info.spi, 0x00); // 配置成 从上到下、从左到右RGB像素格式 _write_data_8bit(lcd->info.spi, 0x00); // 配置成 从上到下、从左到右RGB像素格式
@ -417,11 +241,8 @@ static int32_t _init(lcd_t *lcd)
// 以下进行一些驱动的默认设置 // 以下进行一些驱动的默认设置
lcd->driver.set_dir(lcd, Direction_V); // 默认竖屏显示 lcd->driver.set_dir(lcd, Direction_V); // 默认竖屏显示
lcd->driver.full_fill(lcd, LCD_BLACK); // 默认背景色为黑色 lcd->info.back_color = 0x0000; // 默认背景色为黑色
lcd->driver.set_color(lcd, LCD_WHITE); // 默认画笔颜色为白色
lcd->driver.clear(lcd); // 清除屏幕 lcd->driver.clear(lcd); // 清除屏幕
lcd->driver.set_asscii_font(lcd, &ascii_font_24); // 默认ASCII字体
lcd->info.show_num_mode = FILL_ZERO; // 设置变量显示模式多余位填充空格还是填充0
return 0; return 0;
} }
@ -432,11 +253,7 @@ void lcd_tft_154_init(lcd_driver_t *driver)
driver->init = _init; // 已实现 driver->init = _init; // 已实现
driver->set_dir = _set_dir; // 已实现 driver->set_dir = _set_dir; // 已实现
driver->set_color = _set_color; // 已实现
driver->set_address = _set_address; // 已实现 driver->set_address = _set_address; // 已实现
driver->set_asscii_font = _set_asscii_font; // 已实现 driver->write_pixels = _write_pixels; // 已实现
driver->set_hz_font = _set_hz_font; // 已实现
driver->display_text = _display_text; // 已实现
driver->clear = _clear; // 已实现 driver->clear = _clear; // 已实现
driver->full_fill = _full_fill; // 已实现
} }

View File

@ -205,6 +205,7 @@ typedef struct
void (*display_text)(lcd_t *lcd, uint16_t x, uint16_t y, char *text); // 显示字符串 void (*display_text)(lcd_t *lcd, uint16_t x, uint16_t y, char *text); // 显示字符串
void (*full_fill)(lcd_t *lcd, uint32_t color); void (*full_fill)(lcd_t *lcd, uint32_t color);
void (*set_address)(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); // 设置显示区域 void (*set_address)(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); // 设置显示区域
void (*write_pixels)(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *data); // 写像素缓冲区
void (*clear)(lcd_t *lcd); // 清屏 void (*clear)(lcd_t *lcd); // 清屏
void (*set_clear_flag)(lcd_t *lcd); // 设置清屏标志 void (*set_clear_flag)(lcd_t *lcd); // 设置清屏标志
void (*copy_template)(lcd_t *lcd, template_copy_type_e dir); // 拷贝模板 0,拷贝pri_template到pri1拷贝pri到pri_template; 其余清空 void (*copy_template)(lcd_t *lcd, template_copy_type_e dir); // 拷贝模板 0,拷贝pri_template到pri1拷贝pri到pri_template; 其余清空
@ -216,8 +217,7 @@ typedef struct
// 获取接口 // 获取接口
uint8_t (*get_dir)(lcd_t *lcd); // 获取扫描方向 uint8_t (*get_dir)(lcd_t *lcd); // 获取扫描方向
BOOL(*get_clear_flag) BOOL (*get_clear_flag)(lcd_t *lcd); // 获取清屏标志
(lcd_t *lcd); // 获取清屏标志
__IO BOOL idel; // 是否空闲 __IO BOOL idel; // 是否空闲
} lcd_driver_t; } lcd_driver_t;

View File

@ -0,0 +1,28 @@
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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(${CMAKE_CURRENT_LIST_DIR}/core/build.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/draw/build.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/fonts/build.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/mm/build.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/widgets/build.cmake)

View File

@ -0,0 +1,33 @@
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/sgl_core.c
${CMAKE_CURRENT_LIST_DIR}/sgl_log.c
${CMAKE_CURRENT_LIST_DIR}/sgl_math.c
${CMAKE_CURRENT_LIST_DIR}/sgl_event.c
${CMAKE_CURRENT_LIST_DIR}/sgl_anim.c
${CMAKE_CURRENT_LIST_DIR}/sgl_snprintf.c
${CMAKE_CURRENT_LIST_DIR}/sgl_misc.c
)

View File

@ -0,0 +1,31 @@
# source/core/lm.cfg
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
SRC += sgl_core.c
SRC += sgl_log.c
SRC += sgl_math.c
SRC += sgl_event.c
SRC += sgl_anim.c
SRC += sgl_misc.c
SRC += sgl_snprintf.c

View File

@ -0,0 +1,422 @@
/* source/core/sgl_anim.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_anim.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#if (CONFIG_SGL_ANIMATION)
sgl_anim_ctx_t sgl_anim_ctx = {
.anim_list_head = NULL,
.anim_list_tail = NULL,
};
/**
* @brief Animation static initialization
* @param anim - Animation object
* @return none
*/
void sgl_anim_init(sgl_anim_t *anim)
{
anim->next = NULL;
anim->data = NULL;
anim->act_delay = 0;
anim->act_duration = 0;
anim->start_value = 0;
anim->end_value = 0;
anim->path_cb = NULL;
anim->path_algo = NULL;
anim->finish_cb = NULL;
anim->auto_free = 0;
anim->finished = 1;
}
/**
* @brief dynamic alloc animation object with initialization
* @param none
* @return animation object
*/
sgl_anim_t* sgl_anim_create(void)
{
sgl_anim_t *anim = sgl_malloc(sizeof(sgl_anim_t));
if (anim == NULL) {
SGL_LOG_ERROR("sgl_anim_create: malloc failed");
return NULL;
}
sgl_anim_init(anim);
return anim;
}
/**
* @brief add animation object to animation list
* @param anim animation object
* @return none
*/
static void sgl_anim_add(sgl_anim_t *anim)
{
if (sgl_anim_ctx.anim_list_tail != NULL) {
sgl_anim_ctx.anim_list_tail->next = anim;
sgl_anim_ctx.anim_list_tail = anim;
}
else {
sgl_anim_ctx.anim_list_head = anim;
sgl_anim_ctx.anim_list_tail = anim;
}
anim->next = NULL;
anim->finished = 0;
}
/**
* @brief remove animation object from animation list
* @param anim animation object
* @return none
*/
static void sgl_anim_remove(sgl_anim_t *anim)
{
SGL_ASSERT(anim != NULL);
sgl_anim_t *prev = NULL;
if (sgl_anim_ctx.anim_list_head == anim) {
sgl_anim_ctx.anim_list_head = anim->next;
if (sgl_anim_ctx.anim_list_head == NULL) {
sgl_anim_ctx.anim_list_tail = NULL;
}
return;
}
prev = sgl_anim_ctx.anim_list_head;
while (prev != NULL && prev->next != anim) {
prev = prev->next;
}
if (prev == NULL) {
return;
}
prev->next = anim->next;
if (anim == sgl_anim_ctx.anim_list_tail) {
sgl_anim_ctx.anim_list_tail = prev;
}
}
/**
* @brief start animation
* @param anim animation object
* @para repeat_cnt repeat count of animation
* @return none
*/
void sgl_anim_start(sgl_anim_t *anim, uint32_t repeat_cnt)
{
SGL_ASSERT(anim != NULL);
if (anim->finished && repeat_cnt) {
sgl_anim_add(anim);
anim->finished = 0;
}
anim->act_delay = sgl_tick_get();
anim->repeat_cnt = repeat_cnt & SGL_ANIM_REPEAT_LOOP;
}
/**
* @brief stop animation
* @param anim animation object
* @return none
*/
void sgl_anim_stop(sgl_anim_t *anim)
{
SGL_ASSERT(anim != NULL);
if (!anim->finished) {
sgl_anim_remove(anim);
anim->finished = 1;
}
anim->act_delay = 0;
}
/**
* @brief delete animation object
* @param anim animation object
* @return none
*/
void sgl_anim_delete(sgl_anim_t *anim)
{
SGL_ASSERT(anim != NULL);
if (!anim->finished) {
sgl_anim_stop(anim);
}
sgl_free(anim);
}
/**
* @brief animation task, it will foreach all animation
* @param none
* @return none
* @note this function should be called in sgl_task()
*/
void sgl_anim_task(void)
{
int32_t value = 0;
uint32_t elaps_time = 0, act_time = 0;
sgl_anim_t *anim = sgl_anim_ctx.anim_list_head, *next = NULL;
while (anim != NULL) {
act_time = sgl_tick_get();
if(act_time < anim->act_delay) {
continue;
}
elaps_time = act_time - anim->act_delay;
/* check callback function for debug */
SGL_ASSERT(anim->path_cb != NULL);
SGL_ASSERT(anim->path_algo != NULL);
value = anim->path_algo(sgl_min(elaps_time, anim->act_duration), anim->act_duration, anim->start_value, anim->end_value);
anim->path_cb(anim, value);
if (elaps_time > anim->act_duration) {
if (anim->repeat_cnt != SGL_ANIM_REPEAT_LOOP) {
anim->repeat_cnt--;
}
if (anim->finish_cb) {
anim->finish_cb(anim);
}
/* remove anim object if repeat count is 0 */
if (anim->repeat_cnt == 0) {
sgl_anim_stop(anim);
/* if animation is auto free, free it */
if (anim->auto_free) {
next = anim->next;
sgl_free(anim);
anim = next;
continue;
}
}
anim->act_delay += anim->act_duration;
}
anim = anim->next;
}
}
/**
* Linear animation path calculation function
*
* Calculates the current interpolated value based on elapsed time and total duration
* using linear interpolation.
*
* @param elaps Elapsed time in milliseconds
* @param duration Total animation duration in milliseconds
* @param start Start value
* @param end End value
*
* @return The interpolated value for the current time
*
* @note Returns 'end' if elaps >= duration (animation finished)
* Returns 'start' if elaps == 0 (animation just started)
* Uses 32-bit integer arithmetic to avoid floating-point operations
* for better performance on embedded systems
*/
int32_t sgl_anim_path_linear(uint32_t elaps, uint32_t duration, int32_t start, int32_t end)
{
int64_t progress_fixed, delta, result;
// If duration is zero or elapsed time exceeds duration, return end value
if (duration == 0 || elaps >= duration) {
return (int32_t)end;
}
// If no time has elapsed, return start value
if (elaps == 0) {
return (int32_t)start;
}
// Calculate progress (elaps / duration) as a fixed-point number with 16 fractional bits
// Use 64-bit intermediate to prevent overflow during multiplication
progress_fixed = ((int64_t)elaps << 16) / duration;
// Calculate the difference between end and start
delta = end - start;
// Compute the interpolated result: start + delta * (elaps/duration)
// Right-shift by 16 to scale back from fixed-point representation
result = start + ((delta * progress_fixed) >> 16);
return result;
}
/**
* sgl_anim_path_ease_in_out - Cubic ease-in-out animation path
*
* This function creates a smooth animation curve that starts slow,
* accelerates in the middle, and decelerates at the end.
*
* @param elaps Elapsed time (ms)
* @param duration Total animation duration (ms)
* @param start Start value
* @param end End value
* @return Interpolated value at current time
*/
int32_t sgl_anim_path_ease_in_out(uint32_t elaps, uint32_t duration, int32_t start, int32_t end)
{
int32_t t_180, cos_val, delta;
if (elaps >= duration)
return end;
if (elaps == 0)
return start;
t_180 = (elaps * 180) / duration;
if (t_180 <= 90) {
cos_val = sgl_sin(90 - t_180);
} else {
cos_val = -sgl_sin(t_180 - 90);
}
// Now: progress = 0.5 * (1 - cos_val/1000) = (1000 - cos_val) / 2000
// So: result = start + (end - start) * (1000 - cos_val) / 2000
delta = end - start;
return start + (delta * (32767 - cos_val)) / 65535;
}
/**
* sgl_anim_path_ease_out - Cubic ease-in animation path
*
* This function creates a smooth animation curve that starts accelerates,
* it will be slow in the after
*
* @param elaps Elapsed time (ms)
* @param duration Total animation duration (ms)
* @param start Start value
* @param end End value
* @return Interpolated value at current time
*/
int32_t sgl_anim_path_ease_out(uint32_t elaps, uint32_t duration, int32_t start, int32_t end)
{
int32_t angle, sin_val, delta;
if (elaps >= duration)
return end;
if (elaps == 0)
return start;
// t ∈ [0, 90] degrees: sin(t * 90 / duration)
angle = (elaps * 90) / duration;
sin_val = sgl_sin(angle); // Assume returns 0 ~ 65535 or Q15
// If sgl_sin returns ×1000 (e.g., sin(90) = 32767)
delta = end - start;
return start + ((delta * sin_val) >> 15);
}
/**
* sgl_anim_path_ease_in - Cubic ease-in animation path
*
* This function creates a smooth animation curve that starts accelerates,
* accelerates in the after
*
* @param elaps Elapsed time (ms)
* @param duration Total animation duration (ms)
* @param start Start value
* @param end End value
* @return Interpolated value at current time
*/
int32_t sgl_anim_path_ease_in(uint32_t elaps, uint32_t duration, int32_t start, int32_t end)
{
int32_t angle, cos_val, delta;
if (elaps >= duration)
return end;
if (elaps == 0)
return start;
// t ∈ [0, 90] degrees: sin(t * 90 / duration)
angle = (elaps * 90) / duration;
cos_val = sgl_cos(angle); // Assume returns 0 ~ 65535 or Q15
// If sgl_sin returns ×1000 (e.g., sin(90) = 32767)
delta = end - start;
return start + ((delta * (32767 - cos_val)) >> 15);
}
/**
* sgl_anim_path_overshoot - Overshoot animation path
*
* This function creates an animation curve that overshoots the target end value
* slightly before settling back to it, creating a natural "bounce" or "spring-like"
* effect for a more dynamic and realistic animation.
*
* @param elaps Elapsed time (ms) since the animation started
* @param duration Total animation duration (ms)
* @param start Initial value of the animated property at the start of the animation
* @param end Target end value of the animated property
* @return Interpolated value of the animated property at the current elapsed time
*/
int32_t sgl_anim_path_overshoot(uint32_t elaps, uint32_t duration, int32_t start, int32_t end)
{
int64_t t, t1, t2, inv_t2, ease_back, diff, progress;
if (elaps >= duration)
return end;
t = (int64_t)elaps * 16384 / duration;
diff = end - start;
if (t < 11468) {
t1 = t * 16384 / 11468;
progress = (t1 * (32768 - t1)) >> 14;
progress = (progress * 18841) >> 14;
}
else {
t2 = (t - 11468) * 16384 / (16384 - 11468);
inv_t2 = 16384 - t2;
ease_back = (inv_t2 * inv_t2) >> 14;
progress = 16384 + (ease_back * (18841 - 16384) >> 14);
}
return start + (int32_t)((diff * progress) >> 14);
}
#endif // !CONFIG_SGL_ANIMATION

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,437 @@
/* source/core/sgl_event.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_event.h>
#include <sgl_math.h>
#include <sgl_cfgfix.h>
#include <sgl_log.h>
#include <string.h>
#include <sgl_mm.h>
/* define event queue size */
#define SGL_EVENT_QUEUE_SIZE (CONFIG_SGL_EVENT_QUEUE_SIZE)
#define SGL_EVENT_QUEUE_SIZE_MASK (SGL_EVENT_QUEUE_SIZE - 1)
/**
* @brief event queue struct
* @buffer: event buffer to save all event data
* @head: event queue head which is used to push event
* @tail: event queue tail which is used to pop event
* @count: event queue count which have been pushed
*/
typedef struct event_queue {
sgl_event_t buffer[SGL_EVENT_QUEUE_SIZE];
uint16_t head;
uint16_t tail;
} event_queue_t;
/**
* @brief event context struct
* @last_click: last click object which may be lost event
* @last_touch: last touch position
* @evtq: event queue
*/
static struct event_context {
struct sgl_obj *last_click;
sgl_event_pos_t last_touch;
event_queue_t evtq;
} evt_ctx;
/**
* @brief Initialize the event queue
* @param none
* @return 0 on success, -1 on failure
* @note !!!!!! the SGL_EVENT_QUEUE_SIZE must be power of 2 !!!!!!
* You must check the return value of this function.
*/
int sgl_event_queue_init(void)
{
if (!sgl_is_pow2(SGL_EVENT_QUEUE_SIZE)) {
SGL_LOG_ERROR("The capacity must be power of 2");
return -1;
}
evt_ctx.evtq.head = evt_ctx.evtq.tail = 0;
return 0;
}
/**
* @brief Check whether the event queue is empty
* @param none
* @return true if the event queue is empty, false otherwise
*/
static inline bool sgl_event_queue_is_empty(void)
{
return evt_ctx.evtq.head == evt_ctx.evtq.tail;
}
/**
* @brief Check whether the event queue is full
* @param none
* @return true if the event queue is full, false otherwise
*/
static inline bool sgl_event_queue_is_full(void)
{
uint32_t next_head = (evt_ctx.evtq.head + 1) & SGL_EVENT_QUEUE_SIZE_MASK;
return next_head == evt_ctx.evtq.tail;
}
/**
* @brief Push an event into the event queue
* @param event The event to be pushed
* @return 0 on success, -1 on failure
*/
void sgl_event_queue_push(sgl_event_t event)
{
if (unlikely(sgl_event_queue_is_full())) {
SGL_LOG_ERROR("Event queue is full, maybe system is too slow");
return;
}
evt_ctx.evtq.buffer[evt_ctx.evtq.head] = event;
evt_ctx.evtq.head = ((evt_ctx.evtq.head + 1) & SGL_EVENT_QUEUE_SIZE_MASK);
}
/**
* @brief Pop an event from the event queue
* @param out_event The event to be popped
* @return 0 on success, -1 on failure
*/
static inline int sgl_event_queue_pop(sgl_event_t* out_event)
{
if (sgl_event_queue_is_empty()) {
return -1;
}
*out_event = evt_ctx.evtq.buffer[evt_ctx.evtq.tail];
evt_ctx.evtq.tail = ((evt_ctx.evtq.tail + 1) & SGL_EVENT_QUEUE_SIZE_MASK);
return 0;
}
/**
* @brief Check whether the position is focus on the object
* @param pos The position to be checked
* @param rect The rectangle of the object
* @param radius The radius of the object
* @return true if the position is focus on the object, false otherwise
*/
static bool pos_is_focus_on_obj(sgl_event_pos_t *pos, sgl_rect_t *rect, int16_t radius)
{
if (pos->x < rect->x1 || pos->x > rect->x2 || pos->y < rect->y1 || pos->y > rect->y2) {
return false;
}
else if(radius == 0) {
return true;
}
if ((pos->x >= rect->x1 + radius) && (pos->x <= rect->x2 - radius)) {
return true;
}
else if ((pos->y >= rect->y1 + radius) && (pos->y <= rect->y2 - radius)) {
return true;
}
if (pos->x <= rect->x1 + radius && pos->y <= rect->y1 + radius) {
int16_t dx = pos->x - (rect->x1 + radius);
int16_t dy = pos->y - (rect->y1 + radius);
return sgl_pow2(dx) + sgl_pow2(dy) <= sgl_pow2(radius);
}
else if (pos->x >= rect->x2 - radius && pos->y <= rect->y1 + radius) {
int16_t dx = pos->x - (rect->x2 - radius);
int16_t dy = pos->y - (rect->y1 + radius);
return sgl_pow2(dx) + sgl_pow2(dy) <= sgl_pow2(radius);
}
else if (pos->x <= rect->x1 + radius && pos->y >= rect->y2 - radius) {
int16_t dx = pos->x - (rect->x1 + radius);
int16_t dy = pos->y - (rect->y2 - radius);
return sgl_pow2(dx) + sgl_pow2(dy) <= sgl_pow2(radius);
}
else if (pos->x >= rect->x2 - radius && pos->y >= rect->y2 - radius) {
int16_t dx = pos->x - (rect->x2 - radius);
int16_t dy = pos->y - (rect->y2 - radius);
return sgl_pow2(dx) + sgl_pow2(dy) <= sgl_pow2(radius);
}
return false;
}
/**
* @brief check whether the position is clicked on the object
* @param pos The position to be clicked
* @return The object that is clicked on, NULL if no object is clicked
*/
static struct sgl_obj* click_detect_object(sgl_event_pos_t *pos)
{
struct sgl_obj *stack[SGL_OBJ_DEPTH_MAX], *obj = sgl_screen_act()->child, *find = NULL;
int top = 0;
if (unlikely(obj == NULL)) {
return NULL;
}
stack[top++] = obj;
while (top > 0) {
SGL_ASSERT(top < SGL_OBJ_DEPTH_MAX);
obj = stack[--top];
if (sgl_obj_has_sibling(obj)) {
stack[top++] = obj->sibling;
}
if (unlikely(sgl_obj_is_hidden(obj))) {
continue;
}
if (pos_is_focus_on_obj(pos, &obj->coords, obj->radius)) {
find = obj;
if (sgl_obj_has_child(obj)) {
stack[top++] = obj->child;
}
}
}
/**
* if the object is clickable, return it, otherwise return its parent
* because the object may be a label attached to the object
*/
if (find != NULL) {
return sgl_obj_is_clickable(find) ? find : (sgl_obj_is_clickable(find->parent) ? find->parent : NULL);
}
return find;
}
/**
* @brief Handle the position event
* @param pos The position to be handled
* @param type The type of the event
* @return none
*/
void sgl_event_send_pos(sgl_event_pos_t pos, sgl_event_type_t type)
{
sgl_event_t event = {
.obj = NULL,
.type = type,
.pos = pos,
};
if (type == SGL_EVENT_PRESSED) {
evt_ctx.last_touch = pos;
}
sgl_event_queue_push(event);
}
/**
* @brief get information of motion event type
* @param evt [in][out] event to be handled
* @return none
*/
static void sgl_get_move_info(sgl_event_t *evt)
{
int16_t dx = evt->pos.x - evt_ctx.last_touch.x;
int16_t dy = evt->pos.y - evt_ctx.last_touch.y;
if (sgl_abs(dx) > sgl_abs(dy)) {
if (dx > 0) {
evt->type = SGL_EVENT_MOVE_RIGHT;
evt->distance = dx;
}
else {
evt->type = SGL_EVENT_MOVE_LEFT;
evt->distance = -dx;
}
}
else {
if (dy > 0) {
evt->type = SGL_EVENT_MOVE_DOWN;
evt->distance = dy;
}
else {
evt->type = SGL_EVENT_MOVE_UP;
evt->distance = -dy;
}
}
evt_ctx.last_touch = evt->pos;
}
/**
* @brief All event task in SGL, this function will traverse all elements in the event queue,
* respond to each element with an event, so that all events will trigger and point to the
* corresponding callback function
* @param none
* @return none
*/
void sgl_event_task(void)
{
sgl_event_t evt;
struct sgl_obj *obj = NULL;
/* Get event from event queue */
while (sgl_event_queue_pop(&evt) == 0) {
obj = evt.obj;
/* if obj is NULL, it means the event from the input device */
if (obj == NULL) {
if (evt.type != SGL_EVENT_MOTION) {
obj = click_detect_object(&evt.pos);
} else {
obj = evt_ctx.last_click;
sgl_get_move_info(&evt);
}
}
if (obj) {
evt.pos.x = sgl_clamp(evt.pos.x, obj->coords.x1, obj->coords.x2);
evt.pos.y = sgl_clamp(evt.pos.y, obj->coords.y1, obj->coords.y2);
if (evt.type == SGL_EVENT_PRESSED) {
if (obj->pressed) {
continue;
}
obj->pressed = true;
evt_ctx.last_click = obj;
}
else if (evt.type == SGL_EVENT_RELEASED) {
if (!obj->pressed) {
if (evt_ctx.last_click && evt_ctx.last_click != obj) {
evt.obj = evt_ctx.last_click;
sgl_event_queue_push(evt);
}
continue;
}
obj->pressed = false;
evt_ctx.last_click = NULL;
}
SGL_ASSERT(obj->construct_fn);
evt.param = obj->event_data;
evt.obj = obj;
obj->construct_fn(NULL, obj, &evt);
/* call user event function */
if(obj->event_fn) {
obj->event_fn(&evt);
}
}
else {
SGL_LOG_TRACE("pos is out of object or no event_lost, skip event");
if (evt.type == SGL_EVENT_RELEASED && evt_ctx.last_click != NULL) {
evt.obj = evt_ctx.last_click;
sgl_event_queue_push(evt);
}
}
}
}
/**
* @brief Touch event read, this function will be called by user
* @param x: touch x position
* @param y: touch y position
* @param flag: touch flag, it means touch event down or up:
* true : touch down
* false: touch up
* @return none
* @note: for example, you can call it in 30ms tick handler function
* void example_30ms_tick_handler(void)
* {
* int pos_x, pos_y;
* bool button_status;
*
* bsp_touch_read_pos(&pos_x, &pos_y);
* button_status = bsp_touch_read_status();
*
* sgl_event_pos_input(pos_x, pos_y, button_status);
* }
*/
void sgl_event_pos_input(int16_t x, int16_t y, bool flag)
{
static sgl_event_pos_t last_press, last_motion;
static uint32_t act_count = 0;
sgl_event_pos_t pos = { .x = x, .y = y };
/* rotate touch position */
#if (CONFIG_SGL_FBDEV_ROTATION != 0)
#if (CONFIG_SGL_FBDEV_ROTATION == 90)
pos.x = sgl_min(SGL_SCREEN_WIDTH - y, SGL_SCREEN_WIDTH - 1);
pos.y = sgl_min(x, SGL_SCREEN_HEIGHT - 1);
#elif (CONFIG_SGL_FBDEV_ROTATION == 180)
pos.x = SGL_SCREEN_WIDTH - x - 1;
pos.y = SGL_SCREEN_HEIGHT - y - 1;
#elif (CONFIG_SGL_FBDEV_ROTATION == 270)
pos.x = sgl_min(y, SGL_SCREEN_WIDTH - 1);
pos.y = sgl_min(SGL_SCREEN_HEIGHT - x, SGL_SCREEN_HEIGHT - 1);
#else
#error "CONFIG_SGL_FBDEV_ROTATION is invalid rotation value (only 0/90/180/270 supported)"
#endif
#endif //!CONFIG_SGL_FBDEV_ROTATION
if (flag) {
if (!act_count) {
act_count = 1;
sgl_event_send_pos(pos, SGL_EVENT_PRESSED);
last_press = pos;
SGL_LOG_INFO("Touch SGL_EVENT_PRESSED x: %d, y: %d", pos.x, pos.y);
}
else {
sgl_event_send_pos(pos, SGL_EVENT_MOTION);
last_motion = pos;
SGL_LOG_INFO("Touch SGL_EVENT_MOTION x: %d, y: %d", pos.x, pos.y);
}
act_count ++;
}
else {
if (act_count) {
SGL_LOG_INFO("Touch action count: %d", act_count);
if (last_press.x == last_motion.x && last_press.y == last_motion.y) {
if (act_count < SGL_EVENT_CLICK_INTERVAL) {
sgl_event_send_pos(last_press, SGL_EVENT_CLICKED);
SGL_LOG_INFO("Touch SGL_EVENT_CLICKED x: %d, y: %d", last_press.x, last_press.y);
}
else {
sgl_event_send_pos(last_press, SGL_EVENT_LONG_CLICKED);
SGL_LOG_INFO("Touch SGL_EVENT_LONG_CLICKED x: %d, y: %d", last_press.x, last_press.y);
}
}
act_count = 0;
sgl_event_send_pos(last_motion, SGL_EVENT_RELEASED);
SGL_LOG_INFO("Touch SGL_EVENT_RELEASED x: %d, y: %d", last_motion.x, last_motion.y);
}
}
}

View File

@ -0,0 +1,78 @@
/* source/core/sgl_log.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_log.h>
#include <sgl_core.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#if CONFIG_SGL_DEBUG
/**
* @brief sgl log printing function, used to print debugging information. Note that this function
* should only be called in debugging mode, otherwise it may affect system real-time
* performance due to long execution time
* @param level: log level, such as, INFO, USER...
* @param format: log content
* @return none
*/
void sgl_log(const char *level, const char * format, ...)
{
char buffer[120];
int tail = 0;
int pref_size = strlen(level);
strcpy(buffer, level);
va_list va;
va_start(va, format);
sgl_vsnprintf(buffer + pref_size, sizeof(buffer), format, va);
va_end(va);
tail = strlen(buffer);
memcpy(&buffer[tail], &"\r\n"SGL_LOG_NONE, strlen("\r\n"SGL_LOG_NONE));
buffer[tail + strlen("\r\n"SGL_LOG_NONE)] = 0;
sgl_log_stdout(buffer);
}
/**
* @brief sgl assert handler, used to handle assertions
* @param file: file name
* @param func: function name
* @param line: line number
* @return none
*/
void sgl_assert_handler(const char *file, const char *func, int line)
{
sgl_log(SGL_ASSERT_FLAG, "file: %s, function: %s, line: %d", file, func, line);
while (1) {
};
}
#endif // !CONFIG_SGL_DEBUG

View File

@ -0,0 +1,434 @@
/* source/core/sgl_math.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_math.h>
/**
* @brief sine table
* @note the table is used to calculate the sine of an angle
*/
static const int16_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
};
/**
* @brief sqrt table, if the number less than 1024, the sqrt root will get by the table
*/
static const uint8_t sqrt_error_table[] = {
0x00,0x00,0x6a,0xbb,0x00,0x3c,0x73,0xa5,0xd4,0x00,0x29,0x51,0x76,0x9b,0xbd,0xdf,
0x00,0x1f,0x3e,0x5b,0x78,0x95,0xb0,0xcb,0xe6,0x00,0x19,0x32,0x4a,0x62,0x7a,0x91,
0xa8,0xbe,0xd4,0xea,0x00,0x15,0x2a,0x3e,0x53,0x67,0x7b,0x8e,0xa2,0xb5,0xc8,0xdb,
0xed,0x00,0x12,0x24,0x36,0x47,0x59,0x6a,0x7b,0x8c,0x9d,0xae,0xbe,0xcf,0xdf,0xef,
0x00,0x0f,0x1f,0x2f,0x3f,0x4e,0x5d,0x6d,0x7c,0x8b,0x9a,0xa9,0xb7,0xc6,0xd4,0xe3,
0xf1,0x00,0x0e,0x1c,0x2a,0x38,0x46,0x53,0x61,0x6f,0x7c,0x8a,0x97,0xa4,0xb2,0xbf,
0xcc,0xd9,0xe6,0xf3,0x00,0x0c,0x19,0x26,0x32,0x3f,0x4b,0x58,0x64,0x70,0x7c,0x89,
0x95,0xa1,0xad,0xb9,0xc5,0xd1,0xdc,0xe8,0xf4,0x00,0x0b,0x17,0x22,0x2e,0x39,0x44,
0x50,0x5b,0x66,0x72,0x7d,0x88,0x93,0x9e,0xa9,0xb4,0xbf,0xca,0xd5,0xdf,0xea,0xf5,
0x00,0x0a,0x15,0x1f,0x2a,0x34,0x3f,0x49,0x54,0x5e,0x68,0x73,0x7d,0x87,0x91,0x9c,
0xa6,0xb0,0xba,0xc4,0xce,0xd8,0xe2,0xec,0xf6,0x00,0x09,0x13,0x1d,0x27,0x30,0x3a,
0x44,0x4d,0x57,0x61,0x6a,0x74,0x7d,0x87,0x90,0x99,0xa3,0xac,0xb6,0xbf,0xc8,0xd1,
0xdb,0xe4,0xed,0xf6,0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x51,0x5a,0x63,
0x6c,0x74,0x7d,0x86,0x8f,0x98,0xa0,0xa9,0xb2,0xbb,0xc3,0xcc,0xd5,0xdd,0xe6,0xee,
0xf7,0x00,0x08,0x11,0x19,0x21,0x2a,0x32,0x3b,0x43,0x4c,0x54,0x5c,0x65,0x6d,0x75,
0x7d,0x86,0x8e,0x96,0x9e,0xa7,0xaf,0xb7,0xbf,0xc7,0xcf,0xd7,0xdf,0xe7,0xef,0xf7,
0x00,0x07,0x0f,0x17,0x1f,0x27,0x2f,0x37,0x3f,0x47,0x4f,0x57,0x5e,0x66,0x6e,0x76,
0x7e,0x85,0x8d,0x95,0x9c,0xa4,0xac,0xb4,0xbb,0xc3,0xca,0xd2,0xda,0xe1,0xe9,0xf0,
0xf8,0x00,0x07,0x0f,0x16,0x1e,0x25,0x2c,0x34,0x3b,0x43,0x4a,0x52,0x59,0x60,0x68,
0x6f,0x76,0x7e,0x85,0x8c,0x94,0x9b,0xa2,0xa9,0xb1,0xb8,0xbf,0xc6,0xcd,0xd5,0xdc,
0xe3,0xea,0xf1,0xf8,0x00,0x07,0x0e,0x15,0x1c,0x23,0x2a,0x31,0x38,0x3f,0x46,0x4d,
0x54,0x5b,0x62,0x69,0x70,0x77,0x7e,0x85,0x8c,0x92,0x99,0xa0,0xa7,0xae,0xb5,0xbc,
0xc2,0xc9,0xd0,0xd7,0xde,0xe4,0xeb,0xf2,0xf9,0x00,0x06,0x0d,0x14,0x1a,0x21,0x28,
0x2e,0x35,0x3c,0x42,0x49,0x50,0x56,0x5d,0x64,0x6a,0x71,0x77,0x7e,0x84,0x8b,0x92,
0x98,0x9f,0xa5,0xac,0xb2,0xb9,0xbf,0xc6,0xcc,0xd3,0xd9,0xdf,0xe6,0xec,0xf3,0xf9,
0x00,0x06,0x0c,0x13,0x19,0x1f,0x26,0x2c,0x32,0x39,0x3f,0x45,0x4c,0x52,0x58,0x5f,
0x65,0x6b,0x71,0x78,0x7e,0x84,0x8a,0x91,0x97,0x9d,0xa3,0xa9,0xb0,0xb6,0xbc,0xc2,
0xc8,0xcf,0xd5,0xdb,0xe1,0xe7,0xed,0xf3,0xf9,0x00,0x06,0x0c,0x12,0x18,0x1e,0x24,
0x2a,0x30,0x36,0x3c,0x42,0x48,0x4e,0x54,0x5a,0x60,0x66,0x6c,0x72,0x78,0x7e,0x84,
0x8a,0x90,0x96,0x9c,0xa2,0xa8,0xad,0xb3,0xb9,0xbf,0xc5,0xcb,0xd1,0xd7,0xdc,0xe2,
0xe8,0xee,0xf4,0xfa,0x00,0x05,0x0b,0x11,0x17,0x1d,0x22,0x28,0x2e,0x34,0x39,0x3f,
0x45,0x4b,0x50,0x56,0x5c,0x62,0x67,0x6d,0x73,0x78,0x7e,0x84,0x89,0x8f,0x95,0x9a,
0xa0,0xa6,0xab,0xb1,0xb7,0xbc,0xc2,0xc8,0xcd,0xd3,0xd8,0xde,0xe4,0xe9,0xef,0xf4,
0xfa,0x00,0x05,0x0b,0x10,0x16,0x1b,0x21,0x26,0x2c,0x31,0x37,0x3c,0x42,0x47,0x4d,
0x52,0x58,0x5d,0x63,0x68,0x6e,0x73,0x79,0x7e,0x84,0x89,0x8e,0x94,0x99,0x9f,0xa4,
0xaa,0xaf,0xb4,0xba,0xbf,0xc5,0xca,0xcf,0xd5,0xda,0xdf,0xe5,0xea,0xef,0xf5,0xfa,
0x00,0x05,0x0a,0x0f,0x15,0x1a,0x1f,0x25,0x2a,0x2f,0x35,0x3a,0x3f,0x44,0x4a,0x4f,
0x54,0x5a,0x5f,0x64,0x69,0x6e,0x74,0x79,0x7e,0x83,0x89,0x8e,0x93,0x98,0x9d,0xa3,
0xa8,0xad,0xb2,0xb7,0xbd,0xc2,0xc7,0xcc,0xd1,0xd6,0xdc,0xe1,0xe6,0xeb,0xf0,0xf5,
0xfa,0x00,0x05,0x0a,0x0f,0x14,0x19,0x1e,0x23,0x28,0x2d,0x32,0x38,0x3d,0x42,0x47,
0x4c,0x51,0x56,0x5b,0x60,0x65,0x6a,0x6f,0x74,0x79,0x7e,0x83,0x88,0x8d,0x92,0x97,
0x9c,0xa1,0xa6,0xab,0xb0,0xb5,0xba,0xbf,0xc4,0xc9,0xce,0xd3,0xd8,0xdd,0xe2,0xe7,
0xec,0xf1,0xf6,0xfb,0x00,0x04,0x09,0x0e,0x13,0x18,0x1d,0x22,0x27,0x2c,0x31,0x35,
0x3a,0x3f,0x44,0x49,0x4e,0x53,0x58,0x5c,0x61,0x66,0x6b,0x70,0x75,0x79,0x7e,0x83,
0x88,0x8d,0x92,0x96,0x9b,0xa0,0xa5,0xaa,0xae,0xb3,0xb8,0xbd,0xc2,0xc6,0xcb,0xd0,
0xd5,0xd9,0xde,0xe3,0xe8,0xed,0xf1,0xf6,0xfb,0x00,0x04,0x09,0x0e,0x12,0x17,0x1c,
0x21,0x25,0x2a,0x2f,0x33,0x38,0x3d,0x42,0x46,0x4b,0x50,0x54,0x59,0x5e,0x62,0x67,
0x6c,0x70,0x75,0x7a,0x7e,0x83,0x88,0x8c,0x91,0x96,0x9a,0x9f,0xa3,0xa8,0xad,0xb1,
0xb6,0xbb,0xbf,0xc4,0xc8,0xcd,0xd2,0xd6,0xdb,0xdf,0xe4,0xe9,0xed,0xf2,0xf6,0xfb,
0x00,0x04,0x09,0x0d,0x12,0x16,0x1b,0x1f,0x24,0x29,0x2d,0x32,0x36,0x3b,0x3f,0x44,
0x48,0x4d,0x51,0x56,0x5a,0x5f,0x63,0x68,0x6c,0x71,0x75,0x7a,0x7e,0x83,0x87,0x8c,
0x90,0x95,0x99,0x9e,0xa2,0xa7,0xab,0xb0,0xb4,0xb9,0xbd,0xc1,0xc6,0xca,0xcf,0xd3,
0xd8,0xdc,0xe1,0xe5,0xe9,0xee,0xf2,0xf7,0xfb,0x00,0x04,0x08,0x0d,0x11,0x16,0x1a,
0x1e,0x23,0x27,0x2c,0x30,0x34,0x39,0x3d,0x41,0x46,0x4a,0x4f,0x53,0x57,0x5c,0x60,
0x64,0x69,0x6d,0x71,0x76,0x7a,0x7e,0x83,0x87,0x8b,0x90,0x94,0x98,0x9d,0xa1,0xa5,
0xaa,0xae,0xb2,0xb7,0xbb,0xbf,0xc4,0xc8,0xcc,0xd0,0xd5,0xd9,0xdd,0xe2,0xe6,0xea,
0xee,0xf3,0xf7,0xfb,0x00,0x04,0x08,0x0c,0x11,0x15,0x19,0x1d,0x22,0x26,0x2a,0x2e,
0x33,0x37,0x3b,0x3f,0x43,0x48,0x4c,0x50,0x54,0x59,0x5d,0x61,0x65,0x69,0x6e,0x72,
0x76,0x7a,0x7e,0x83,0x87,0x8b,0x8f,0x93,0x98,0x9c,0xa0,0xa4,0xa8,0xac,0xb1,0xb5,
0xb9,0xbd,0xc1,0xc5,0xca,0xce,0xd2,0xd6,0xda,0xde,0xe3,0xe7,0xeb,0xef,0xf3,0xf7,
0xfb,0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c,0x20,0x25,0x29,0x2d,0x31,0x35,0x39,
0x3d,0x41,0x45,0x49,0x4e,0x52,0x56,0x5a,0x5e,0x62,0x66,0x6a,0x6e,0x72,0x76,0x7a,
0x7e,0x83,0x87,0x8b,0x8f,0x93,0x97,0x9b,0x9f,0xa3,0xa7,0xab,0xaf,0xb3,0xb7,0xbb,
0xbf,0xc3,0xc7,0xcb,0xcf,0xd3,0xd7,0xdb,0xdf,0xe3,0xe7,0xeb,0xef,0xf3,0xf7,0xfb,
0x00
};
/**
* the table will used to calculate the square root of a number
*/
static const uint8_t sqrt_error_init_table[32] = {
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5,
5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7
};
/**
* @brief Calculate the sine of an angle
* @param angle: Angle in degrees such 0-359
* @return sine of the angle from sin0_90_table
* @note This function has implemented angle normalization to the range of 0 to 360 degrees.
*/
int32_t sgl_sin(int16_t angle)
{
int16_t ret = 0;
while (angle >= 360) {
angle -= 360;
}
while (angle < 0) {
angle += 360;
}
if (angle < 0) {
angle = 360 + angle;
}
if (angle < 90) {
ret = sin0_90_table[angle];
}
else if (angle >= 90 && angle < 180){
angle = 180 - angle;
ret = sin0_90_table[angle];
}
else if (angle >= 180 && angle < 270){
angle = angle - 180;
ret = -sin0_90_table[angle];
}
else {
angle = 360 - angle;
ret = -sin0_90_table[angle];
}
return ret;
}
/**
* @brief Calculate x number square root
* @param x: x number
* @retval x number square root
*/
uint16_t sgl_sqrt(uint32_t x)
{
uint32_t rem = 0;
uint32_t root = 0;
uint32_t divisor = 0;
for (int i=0; i<16; i++) {
root <<= 1;
rem = ((rem << 2) + (x >> 30));
x <<= 2;
divisor = (root<<1) + 1;
if (divisor <= rem) {
rem -= divisor;
root++;
}
}
return (uint16_t)(root);
}
/**
* @brief Calculate error of the square root for a number.
* @param x The number to calculate the error for.
* @return The error of the square root. [0 ~ 255]
*/
uint8_t sgl_sqrt_error(uint32_t x)
{
uint32_t bsh = (1 << 14);
uint32_t fpr = 0;
uint32_t osh = 0;
uint32_t bod;
if (x < 1025) {
return sqrt_error_table[x];
}
else if (x > (1 << 30)) {
return 0;
}
int32_t index = 0;
uint32_t xp = x;
if ((xp & 0xFFFF0000) == 0) { index += 16; xp <<= 16; }
if ((xp & 0xFF000000) == 0) { index += 8; xp <<= 8; }
if ((xp & 0xF0000000) == 0) { index += 4; xp <<= 4; }
if ((xp & 0xC0000000) == 0) { index += 2; xp <<= 2; }
if ((xp & 0x80000000) == 0) { index += 1; }
osh = sqrt_error_init_table[31 - index];
bsh = 1 << (2 * osh + 14);
do {
bod = bsh + fpr;
if (x >= bod) {
x -= bod;
fpr = bsh + bod;
}
x <<= 1;
}while (bsh >>= 1);
return fpr>>osh;
}
/**
* @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm
* implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm)
*
* @param x: The x coordinate on a circle
* @param y: The y coordinate on a circle
* @return angle
* @note return angle [-32767 ~ 32767]
*/
int32_t sgl_atan2_raw(int x, int y)
{
int32_t ret;
if (y == 0) {
if (x > 0) {
ret = -32767;
}
else {
ret = 32767;
}
}
else {
ret = (x << 8) / y;
}
if (y > 0) {
ret += 32767;
}
else {
ret -= 32767;
}
return ret;
}
/**
* @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm
* implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm)
*
* @param x: The x coordinate on a circle
* @param y: The y coordinate on a circle
* @return angle
* @note return angle [0 ~ 359]
*/
uint16_t sgl_atan2_angle(int x, int y)
{
unsigned char negflag;
unsigned char tempdegree;
unsigned char comp;
unsigned int degree;
unsigned int ux;
unsigned int uy;
negflag = 0;
if (x < 0) {
negflag += 0x01;
x = (0 - x);
}
ux = x;
if (y < 0) {
negflag += 0x02;
y = (0 - y);
}
uy = y;
if (ux > uy) {
degree = (uy * 45) / ux;
negflag += 0x10;
}
else {
degree = (ux * 45) / uy;
}
comp = 0;
tempdegree = degree;
if (tempdegree > 22) {
if (tempdegree <= 44) comp++;
if (tempdegree <= 41) comp++;
if (tempdegree <= 37) comp++;
if (tempdegree <= 32) comp++;
}
else {
if (tempdegree >= 2) comp++;
if (tempdegree >= 6) comp++;
if (tempdegree >= 10) comp++;
if (tempdegree >= 15) comp++;
}
degree += comp;
if (negflag & 0x10) degree = (90 - degree);
if (negflag & 0x02) {
if (negflag & 0x01)
degree = (180 + degree);
else
degree = (180 - degree);
}
else {
if (negflag & 0x01)
degree = (360 - degree);
}
return degree;
}
/**
* @brief Split the length into n parts, with the weight of each part.
* @param weight: The weight of each part.
* @param count: The count of parts.
* @param length: The length to split.
* @param gap: The gap between each part.
* @param out: The length of each part.
* @note The error accumulation method of Bresenham's algorithm
*/
void sgl_split_len(const uint8_t *weight, int count, int16_t length, int16_t gap, int16_t *out)
{
int16_t total_w = 0, span = 0, accumulated = 0, error = 0;
for (int i = 0; i < count; i++) {
total_w += weight[i];
}
span = length - gap * (count + 1);
for (int i = 0; i < count; i++) {
int numerator = weight[i] * span;
out[i] = numerator / total_w;
error += numerator % total_w;
if (error >= total_w) {
out[i] += 1;
error -= total_w;
}
accumulated += out[i];
}
error = span - accumulated;
for (int i = 0; i < count && error > 0; i++) {
out[i] += 1;
error --;
}
for (int i = 0; i < count && error < 0; i++) {
out[i] -= 1;
error ++;
}
}
/**
* @brief Split the length into n parts, with the weight of each part.
* @param length: The length to split.
* @param count: The count of parts.
* @param gap: The gap between each part.
* @param out: The length of each part.
* @note The average method of Bresenham's algorithm
*/
void sgl_split_len_avg(int length, int count, int16_t gap, int16_t *out)
{
int16_t available_length = length - (count + 1) * gap;
int16_t base = available_length / count;
int16_t remainder = available_length % count;
int16_t error = 0;
for (int i = 0; i < count; i++) {
out[i] = base;
error += remainder;
if (error > count / 2) {
out[i] += 1;
error -= count;
}
}
}
/* Random number generator */
static size_t rand_next = 1;
/**
* @brief Generate a random number.
* @param none
* @return Random number.
* @note The random number generator is in the range of [0, 32767].
*/
int16_t sgl_rand(void)
{
rand_next = rand_next * 1103515245 + 12345;
return (int16_t)((rand_next >> 16) & 0x7FFF);
}
/**
* @brief Set the seed of the random number generator.
* @param seed: The seed of the random number generator.
* @return none
*/
void sgl_srand(unsigned int seed)
{
rand_next = seed;
}

View File

@ -0,0 +1,166 @@
/* source/core/sgl_misc.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl.h>
#if (CONFIG_SGL_BOOT_LOGO)
typedef struct sgl_logo {
sgl_obj_t obj;
uint8_t progress;
uint8_t alpha;
}sgl_logo_t;
#define SGL_LOGO_W (26)
#define SGL_LOGO_H (14)
const uint8_t sgl_logo_s[][4] = {
{0, 0, 8, 2},
{0, 2, 2, 8},
{2, 6, 8, 8},
{6, 8, 8, 14},
{0, 12, 6, 14},
};
const uint8_t sgl_logo_g[][4] = {
{9, 0, 17, 2},
{9, 2, 11, 14},
{11, 12, 17, 14},
{15, 6, 17, 12},
{13, 6, 15, 8},
};
const uint8_t sgl_logo_l[][4] = {
{18, 0, 20, 14},
{20, 12, 26, 14},
};
static void sgl_logo_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_logo_t *logo = (sgl_logo_t*)obj;
int16_t w = obj->area.x2 - obj->area.x1 + 1;
int16_t h = obj->area.y2 - obj->area.y1 + 1;
const float scale_x = w / SGL_LOGO_W;
const float scale_y = h / SGL_LOGO_H;
sgl_rect_t rect;
if(evt->type == SGL_EVENT_DRAW_MAIN) {
sgl_area_t clip;
if (!sgl_surf_clip(surf, &obj->area, &clip)) {
return;
}
for (uint32_t i = 0; i < SGL_ARRAY_SIZE(sgl_logo_s); i++) {
rect.x1 = sgl_logo_s[i][0] * scale_x + obj->area.x1;
rect.y1 = sgl_logo_s[i][1] * scale_y + obj->area.y1;
rect.x2 = sgl_logo_s[i][2] * scale_x + obj->area.x1 - 1;
rect.y2 = sgl_logo_s[i][3] * scale_y + obj->area.y1 - 1;
sgl_draw_fill_rect_with_border(surf, &clip, &rect, obj->radius, SGL_COLOR_RED, SGL_COLOR_BLUE, 0, logo->alpha);
}
for (uint32_t i = 0; i < SGL_ARRAY_SIZE(sgl_logo_g); i++) {
rect.x1 = sgl_logo_g[i][0] * scale_x + obj->area.x1;
rect.y1 = sgl_logo_g[i][1] * scale_y + obj->area.y1;
rect.x2 = sgl_logo_g[i][2] * scale_x + obj->area.x1 - 1;
rect.y2 = sgl_logo_g[i][3] * scale_y + obj->area.y1 - 1;
sgl_draw_fill_rect_with_border(surf, &clip, &rect, obj->radius, SGL_COLOR_GREEN, SGL_COLOR_BLUE, 0, logo->alpha);
}
for (uint32_t i = 0; i < SGL_ARRAY_SIZE(sgl_logo_l); i++) {
rect.x1 = sgl_logo_l[i][0] * scale_x + obj->area.x1;
rect.y1 = sgl_logo_l[i][1] * scale_y + obj->area.y1;
rect.x2 = sgl_logo_l[i][2] * scale_x + obj->area.x1 - 1;
rect.y2 = sgl_logo_l[i][3] * scale_y + obj->area.y1 - 1;
sgl_draw_fill_rect_with_border(surf, &clip, &rect, obj->radius, SGL_COLOR_BLUE, SGL_COLOR_BLUE, 0, logo->alpha);
}
}
}
sgl_obj_t* sgl_logo_create(sgl_obj_t* parent)
{
sgl_logo_t *logo = sgl_malloc(sizeof(sgl_logo_t));
if (logo == NULL) {
SGL_LOG_ERROR("sgl_logo_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(logo, 0, sizeof(sgl_logo_t));
sgl_obj_t *obj = &logo->obj;
sgl_obj_init(&logo->obj, parent);
obj->construct_fn = sgl_logo_construct_cb;
logo->alpha = SGL_ALPHA_MAX;
sgl_obj_set_border_width(obj, 0);
return obj;
}
void sgl_logo_set_alpha(sgl_obj_t* obj, uint8_t alpha)
{
sgl_logo_t *logo = (sgl_logo_t*)obj;
logo->alpha = alpha;
sgl_obj_set_dirty(obj);
}
void sgl_logo_anim(sgl_anim_t *anim, int32_t value)
{
sgl_obj_t *logo = (sgl_obj_t*)anim->data;
sgl_logo_set_alpha(logo, value);
}
/**
* @brief to show the sgl logo after sgl init
* @param none
* @return none
* @note: you can call this function in your main function to show the sgl logo
*/
void sgl_boot_logo(void)
{
sgl_obj_t *logo = sgl_logo_create(NULL);
sgl_obj_set_size(logo, SGL_SCREEN_WIDTH / 3, SGL_SCREEN_HEIGHT / 3);
sgl_obj_set_pos_align(logo, SGL_ALIGN_CENTER);
sgl_obj_set_radius(logo, 0);
sgl_anim_t *anim = sgl_anim_create();
sgl_anim_set_data(anim, logo);
sgl_anim_set_act_duration(anim, 1000);
sgl_anim_set_start_value(anim, SGL_ALPHA_MAX);
sgl_anim_set_end_value(anim, SGL_ALPHA_MIN);
sgl_anim_set_path(anim, sgl_logo_anim, SGL_ANIM_PATH_LINEAR);
sgl_anim_start(anim, SGL_ANIM_REPEAT_ONCE);
while (!sgl_anim_is_finished(anim)) {
sgl_task_handle();
}
sgl_anim_delete(anim);
sgl_obj_delete(logo);
}
#endif // !CONFIG_SGL_BOOT_LOGO

View File

@ -0,0 +1,306 @@
/* source/core/sgl_snprintf.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
/**
* @brief append a character to the buffer
* @param buf buffer
* @param size buffer size
* @param pos current position
* @param c character to append
*/
static inline void append_char(char *buf, size_t size, size_t *pos, char c)
{
if (*pos + 1 < size) {
buf[*pos] = c;
}
(*pos)++;
}
/**
* @brief append a string to the buffer
* @param buf buffer
* @param size buffer size
* @param pos current position
* @param s string to append
*/
static inline void append_str(char *buf, size_t size, size_t *pos, const char* s)
{
while (*s) append_char(buf, size, pos, *s++);
}
/**
* @brief pad alignment characters (default: space) to the buffer
* @param buf buffer
* @param size buffer size
* @param pos current position
* @param pad_len number of padding characters to append
* @param pad_char padding character (default: ' ')
*/
static inline void pad_align(char *buf, size_t size, size_t *pos, size_t pad_len, char pad_char)
{
for (size_t i = 0; i < pad_len; i++) {
append_char(buf, size, pos, pad_char);
}
}
/**
* @brief calculate the length of an integer when converted to string
* @param val integer value
* @return number of characters of the integer string
*/
static inline size_t int_str_len(int val)
{
if (val == 0) return 1; // Special case: 0 has length 1
size_t len = 0;
bool neg = val < 0;
if (neg) val = -val;
do {
len++;
val /= 10;
} while (val);
return neg ? len + 1 : len; // Add 1 for negative sign
}
/**
* @brief append an integer to the buffer with left/right alignment support
* @param buf buffer
* @param size buffer size
* @param pos current position
* @param val integer to append
* @param width alignment width (0 means no alignment)
* @param left_align whether to use left alignment (true: left, false: right)
*/
static inline void append_int(char *buf, size_t size, size_t *pos, int val, int width, bool left_align)
{
char tmp[64];
int i = 0;
bool neg = val < 0;
size_t num_len = int_str_len(val);
size_t pad_len = 0;
if (width > 0 && (size_t)width > num_len) {
pad_len = (size_t)width - num_len;
}
if (!left_align && pad_len > 0) {
pad_align(buf, size, pos, pad_len, ' ');
}
if (neg) val = -val;
do {
tmp[i++] = '0' + (val % 10);
val /= 10;
} while (val);
if (neg) tmp[i++] = '-';
while (i--) append_char(buf, size, pos, tmp[i]);
if (left_align && pad_len > 0) {
pad_align(buf, size, pos, pad_len, ' ');
}
}
/**
* @brief append a hexadecimal number to the buffer
* @param buf buffer
* @param size buffer size
* @param pos current position
* @param val hexadecimal number to append
* @param upper whether to use uppercase letters
*/
static inline void append_hex(char *buf, size_t size, size_t *pos, unsigned int val, bool upper)
{
char tmp[32];
int i = 0;
const char *digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
do {
tmp[i++] = digits[val & 0xF];
val >>= 4;
} while (val);
while (i--) append_char(buf, size, pos, tmp[i]);
}
/**
* @brief append a float to the buffer
* @param buf buffer
* @param size buffer size
* @param pos current position
* @param val float to append
* @param precision number of decimal places (-1 for default of 6)
*/
static void append_float(char *buf, size_t size, size_t *pos, double val, int precision)
{
int int_part = (int)val;
double frac = val - int_part;
if (val < 0) {
append_char(buf, size, pos, '-');
int_part = -int_part;
frac = -frac;
}
append_int(buf, size, pos, int_part, 0, false);
append_char(buf, size, pos, '.');
int prec = (precision >= 0) ? precision : 6;
for (int i = 0; i < prec; i++) {
frac *= 10;
int d = (int)frac;
append_char(buf, size, pos, '0' + d);
frac -= d;
}
}
/**
* @brief format a string, a simple version of vsnprintf (with width alignment support)
* @param buf buffer
* @param size buffer size
* @param fmt format string
* @param ap argument list
* @return number of characters written
*/
int sgl_vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
{
size_t pos = 0;
while (*fmt) {
char c = *fmt;
if (c != '%') {
append_char(buf, size, &pos, c);
fmt++;
continue;
}
fmt++;
bool left_align = false;
int width = 0;
int precision = -1;
if (*fmt == '-') {
left_align = true;
fmt++;
}
while (*fmt >= '0' && *fmt <= '9') {
width = width * 10 + (*fmt - '0');
fmt++;
}
if (*fmt == '.') {
fmt++;
precision = 0;
while (*fmt >= '0' && *fmt <= '9') {
precision = precision * 10 + (*fmt - '0');
fmt++;
}
}
char spec = *fmt;
switch (spec) {
case 's': {
const char *s = va_arg(ap, const char*);
append_str(buf, size, &pos, s);
break;
}
case 'd': {
int d = va_arg(ap, int);
append_int(buf, size, &pos, d, width, left_align);
break;
}
case 'x': {
unsigned int x = va_arg(ap, unsigned int);
append_hex(buf, size, &pos, x, false);
break;
}
case 'X': {
unsigned int x = va_arg(ap, unsigned int);
append_hex(buf, size, &pos, x, true);
break;
}
case 'f': {
double f = va_arg(ap, double);
append_float(buf, size, &pos, f, precision);
break;
}
case 'c': {
char ch = (char)va_arg(ap, int);
append_char(buf, size, &pos, ch);
break;
}
case '%': {
append_char(buf, size, &pos, '%');
break;
}
default:
append_char(buf, size, &pos, '%');
append_char(buf, size, &pos, spec);
break;
}
fmt++;
}
if (size > 0) {
buf[(pos < size) ? pos : (size - 1)] = '\0';
}
return (int)pos;
}
/**
* @brief format a string, a simple version of snprintf (with width alignment support)
* @param buf buffer
* @param size buffer size
* @param fmt format string
* @param ... arguments
* @return number of characters written
*/
int sgl_snprintf(char *buf, size_t size, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int ret = sgl_vsnprintf(buf, size, fmt, ap);
va_end(ap);
return ret;
}

View File

@ -0,0 +1,34 @@
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/sgl_draw_line.c
${CMAKE_CURRENT_LIST_DIR}/sgl_draw_rect.c
${CMAKE_CURRENT_LIST_DIR}/sgl_draw_circle.c
${CMAKE_CURRENT_LIST_DIR}/sgl_draw_arc.c
${CMAKE_CURRENT_LIST_DIR}/sgl_draw_text.c
${CMAKE_CURRENT_LIST_DIR}/sgl_draw_ring.c
${CMAKE_CURRENT_LIST_DIR}/sgl_draw_icon.c
${CMAKE_CURRENT_LIST_DIR}/sgl_draw_xform.c
)

View File

@ -0,0 +1,32 @@
# source/draw/lm.cfg
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
SRC += sgl_draw_line.c
SRC += sgl_draw_rect.c
SRC += sgl_draw_circle.c
SRC += sgl_draw_arc.c
SRC += sgl_draw_text.c
SRC += sgl_draw_ring.c
SRC += sgl_draw_icon.c
SRC += sgl_draw_xform.c

View File

@ -0,0 +1,244 @@
/* source/draw/sgl_draw_arc.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_log.h>
#include <sgl_math.h>
typedef struct sgl_arc_dot
{
int16_t cx;
int16_t cy;
int16_t r;
uint32_t r2;
uint16_t rmax;
uint16_t outer;
} sgl_arc_dot_t;
static void arc_dot_sin_cos(int16_t cx, int16_t cy, int16_t radius_in, int16_t radius_out, sgl_arc_dot_t *dot,int sin, int cos)
{
int len = (radius_out + radius_in) / 2;
int r = (radius_out - radius_in) / 2;
if (unlikely(r == 0)) {
return;
}
if (sin < 0) {
dot->cx = (sin * len - 16348) / 32768;
}
else {
dot->cx = (sin * len + 16348) / 32768;
}
if (cos<0) {
dot->cy = (cos * len - 16348) / 32768;
}
else {
dot->cy = (cos * len + 16348) / 32768;
}
dot->cx = cx - dot->cx;
dot->cy = cy - dot->cy;
dot->r = r + 1;
dot->r2 = sgl_pow2(r);
dot->rmax = sgl_pow2(r + 1);
dot->outer = 0;
}
static inline uint8_t arc_get_dot(sgl_arc_dot_t *dot,int ax, int ay)
{
uint32_t temp;
uint8_t alpha = SGL_ALPHA_MIN, max = SGL_ALPHA_MIN;
sgl_arc_dot_t *p = dot;
int32_t rate = (0xff00) / (dot->rmax - dot->r2);
for (int k = 0; k < 2; k++, p++) {
int x = ax > p->cx ? ax - p->cx : p->cx-ax;
int y = ay > p->cy ? ay - p->cy : p->cy-ay;
if ((x < p->r) && (y < p->r)) {
temp = sgl_pow2(x) + sgl_pow2(y);
if (temp >= p->rmax) {
alpha = 0;
}
else if (temp > p->r2) {
if(dot->outer==0) {
dot->outer = rate;
}
alpha = (p->rmax - temp) * dot->outer >> 8;
}
else {
alpha = SGL_ALPHA_MAX;
}
max = sgl_max(max, alpha);
}
}
return max;
}
/**
* @brief draw an arc with alpha
* @param surf pointer to surface
* @param area pointer to area
* @param desc pointer to arc description
* @return none
*/
void sgl_draw_fill_arc(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_arc_t *desc)
{
int y2 = 0, real_r2 = 0, edge_alpha = 0;
int in_r2 = sgl_pow2(desc->radius_in);
int out_r2 = sgl_pow2(desc->radius_out);
int inv_inner = 0, inv_outer = 0;
sgl_arc_dot_t arc_dot[2];
int in_r2_max = sgl_pow2(desc->radius_in - 1);
int out_r2_max = sgl_pow2(desc->radius_out + 1);
int32_t rate = (0xff00) / (in_r2 - in_r2_max);
int32_t rate2 = (0xff00) / (out_r2_max - out_r2);
sgl_color_t *buf = NULL, *blend = NULL;
int32_t dx, dy;
uint8_t flag = 0xff, in_range;
int32_t ds = 0, de = 0, sd = 0, ed = 0;
int32_t sx = 0, sy = 0, ex = 0, ey = 0;
sgl_color_t tmp_color;
sgl_area_t clip = SGL_AREA_MAX;
sgl_surf_clip_area_return(surf, area, &clip);
sgl_area_t c_rect = {
.x1 = desc->cx - desc->radius_out,
.x2 = desc->cx + desc->radius_out,
.y1 = desc->cy - desc->radius_out,
.y2 = desc->cy + desc->radius_out
};
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
if (desc->start_angle != 0 || desc->end_angle != 360) {
flag = (desc->end_angle - desc->start_angle > 180) ? 1 : 0;
sx = sgl_sin(desc->start_angle);
sy = -sgl_cos(desc->start_angle);
ex = sgl_sin(desc->end_angle);
ey = -sgl_cos(desc->end_angle);
if (desc->mode == SGL_ARC_MODE_NORMAL_SMOOTH || desc->mode == SGL_ARC_MODE_RING_SMOOTH) {
arc_dot_sin_cos(desc->cx, desc->cy, desc->radius_in, desc->radius_out, &arc_dot[0], sx, sy);
arc_dot_sin_cos(desc->cx, desc->cy, desc->radius_in, desc->radius_out, &arc_dot[1], ex, ey);
}
sx = sx >> 7;
sy = sy >> 7;
ex = ex >> 7;
ey = ey >> 7;
}
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
dy = y - desc->cy;
y2 = sgl_pow2(dy);
blend = buf;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
dx = x - desc->cx;
real_r2 = sgl_pow2(x - desc->cx) + y2;
if (real_r2 >= out_r2_max) {
if (x > desc->cx) {
blend++;
break;
}
continue;
}
if (real_r2 < in_r2_max) {
if (x < desc->cx) {
blend += ((desc->cx - x) * 2);
x = desc->cx * 2 - x;
}
continue;
}
if (real_r2 < in_r2 ) {
if(inv_inner == 0) {
inv_inner = rate;
}
edge_alpha = (real_r2 - in_r2_max) * inv_inner >> 8;
}
else if (real_r2 > out_r2) {
if(inv_outer == 0) {
inv_outer = rate2;
}
edge_alpha = (out_r2_max - real_r2) * inv_outer >> 8;
}
else {
edge_alpha = SGL_ALPHA_MAX;
}
tmp_color = desc->color;
if (flag != 255) {
ds = (dx * sy - dy * sx);
de = (dy * ex - dx * ey);
in_range = flag > 0 ? (ds > 0 || de >0) : (ds >= 0 && de >= 0);
if (!in_range) {
switch (desc->mode) {
case SGL_ARC_MODE_NORMAL:
sd = sgl_xy_has_component(dx,dy, sx, sy) ? sgl_abs(ds) : 256;
ed = sgl_xy_has_component(dx,dy, ex, ey) ? sgl_abs(de) : 256;
dx = sgl_min(sd, ed);
tmp_color = (dx < SGL_ALPHA_MAX) ? sgl_color_mixer(desc->color, *blend, sgl_min(255 - dx, edge_alpha)) : *blend;
break;
case SGL_ARC_MODE_RING:
sd = sgl_xy_has_component(dx,dy, sx, sy) ? sgl_abs(ds) : 256;
ed = sgl_xy_has_component(dx,dy, ex, ey) ? sgl_abs(de) : 256;
dx = sgl_min(sd, ed);
tmp_color = (dx < SGL_ALPHA_MAX) ? sgl_color_mixer(desc->color, desc->bg_color, sgl_min(255 - dx, edge_alpha)) : desc->bg_color;
break;
case SGL_ARC_MODE_NORMAL_SMOOTH:
dx = arc_get_dot(arc_dot, x, y);
tmp_color = (dx < SGL_ALPHA_MAX) ? sgl_color_mixer(desc->color, *blend, dx) : desc->color;
break;
case SGL_ARC_MODE_RING_SMOOTH:
dx = arc_get_dot(arc_dot, x, y);
tmp_color = (dx < SGL_ALPHA_MAX) ? sgl_color_mixer(desc->color, desc->bg_color, dx) : desc->color;
break;
default: break;
}
}
}
*blend = desc->alpha == SGL_ALPHA_MAX ? sgl_color_mixer(tmp_color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(tmp_color, *blend, edge_alpha), *blend, desc->alpha);
}
buf += surf->w;
}
}

View File

@ -0,0 +1,299 @@
/* source/draw/sgl_draw_circle.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
/**
* @brief Draw a circle
* @param surf Surface
* @param area Area of the circle
* @param cx X coordinate of the center
* @param cy Y coordinate of the center
* @param radius Radius of the circle
* @param color Color of the circle
* @param alpha Alpha of the circle
* @return none
*/
void sgl_draw_fill_circle(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, sgl_color_t color, uint8_t alpha)
{
sgl_area_t clip = SGL_AREA_MAX;
sgl_color_t *buf = NULL, *blend = NULL;
sgl_surf_clip_area_return(surf, area, &clip);
sgl_area_t c_rect = {
.x1 = cx - radius,
.x2 = cx + radius,
.y1 = cy - radius,
.y2 = cy + radius
};
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
int y2 = 0, real_r2 = 0, edge_alpha = 0;
int r2 = sgl_pow2(radius);
int r2_edge = sgl_pow2(radius + 1);
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
y2 = sgl_pow2(y - cy);
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
real_r2 = sgl_pow2(x - cx) + y2;
if (real_r2 >= r2_edge) {
if(x > cx)
break;
continue;
}
else if (real_r2 >= r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(color, *blend, edge_alpha), *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
}
}
buf += surf->w;
}
}
#if (!CONFIG_SGL_PIXMAP_BILINEAR_INTERP)
/**
* @brief Draw a circle with pixmap and alpha
* @param surf Surface
* @param area Area of the circle
* @param cx X coordinate of the center
* @param cy Y coordinate of the center
* @param radius Radius of the circle
* @param pixmap Pixmap of image
* @param alpha Alpha of the circle
* @return none
*/
void sgl_draw_fill_circle_pixmap(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha)
{
int y2 = 0, real_r2 = 0, s_x = cx - radius, s_y = cy - radius;
int r2 = radius * radius;
int r2_max = (radius + 1) * (radius + 1);
sgl_color_t *buf = NULL, *pbuf = NULL, *blend = NULL;
sgl_area_t clip = SGL_AREA_MAX;
uint8_t edge_alpha = 0;
sgl_surf_clip_area_return(surf, area, &clip);
sgl_area_t c_rect = {
.x1 = cx - radius,
.x2 = cx + radius,
.y1 = cy - radius,
.y2 = cy + radius
};
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
uint32_t scale_x = (pixmap->width << SGL_FIXED_SHIFT) / (radius * 2);
uint32_t scale_y = (pixmap->height << SGL_FIXED_SHIFT) / (radius * 2);
uint32_t step_x = 0, step_y = 0;
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
y2 = sgl_pow2(y - cy);
step_y = (scale_y * (y - s_y)) >> SGL_FIXED_SHIFT;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
real_r2 = sgl_pow2(x - cx) + y2;
step_x = (scale_x * (x - s_x)) >> SGL_FIXED_SHIFT;
pbuf = sgl_pixmap_get_buf(pixmap, step_x, step_y);
if (real_r2 >= r2_max) {
if(x > cx)
break;
continue;
}
else if (real_r2 >= r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(*pbuf, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(*pbuf, *blend, edge_alpha), *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha));
}
}
buf += surf->w;
}
}
#else
void sgl_draw_fill_circle_pixmap(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha)
{
int y2 = 0, real_r2 = 0, s_x = cx - radius, s_y = cy - radius;
int r2 = radius * radius;
int r2_max = (radius + 1) * (radius + 1);
sgl_color_t *buf = NULL, *blend = NULL, ip_color, *pix = (sgl_color_t *)pixmap->bitmap.array;
sgl_area_t clip = SGL_AREA_MAX;
uint8_t edge_alpha = 0;
int fx = 0, fy = 0;
sgl_surf_clip_area_return(surf, area, &clip);
sgl_area_t c_rect = {
.x1 = cx - radius,
.x2 = cx + radius,
.y1 = cy - radius,
.y2 = cy + radius
};
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
const int32_t scale_x = ((int32_t)pixmap->width << SGL_FIXED_SHIFT) / (radius * 2);
const int32_t scale_y = ((int32_t)pixmap->height << SGL_FIXED_SHIFT) / (radius * 2);
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
y2 = sgl_pow2(y - cy);
fy = (int32_t)(y - s_y) * scale_y;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
real_r2 = sgl_pow2(x - cx) + y2;
fx = (int32_t)(x - s_x) * scale_x;
ip_color = sgl_draw_biln_color(pix, pixmap->width, pixmap->height, fx, fy);
if (real_r2 >= r2_max) {
if(x > cx)
break;
continue;
}
else if (real_r2 >= r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(ip_color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(ip_color, *blend, edge_alpha), *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? ip_color : sgl_color_mixer(ip_color, *blend, alpha));
}
}
buf += surf->w;
}
}
#endif // CONFIG_SGL_PIXMAP_BILINEAR_INTERP
/**
* @brief Draw a circle with alpha and border
* @param surf Surface
* @param area Area of the circle
* @param cx X coordinate of the center
* @param cy Y coordinate of the center
* @param radius Radius of the circle
* @param color Color of the circle
* @param border_color Color of the border
* @param border_width Width of the border
* @param alpha Alpha of the circle
* @return none
*/
void sgl_draw_fill_circle_with_border(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, sgl_color_t color, sgl_color_t border_color, int16_t border_width, uint8_t alpha)
{
int radius_in = sgl_max(radius - border_width + 1, 0);
int y2 = 0, real_r2 = 0;
int in_r2 = sgl_pow2(radius_in);
int out_r2 = sgl_pow2(radius);
sgl_color_t *buf = NULL, *blend = NULL;
int in_r2_max = sgl_pow2(radius_in - 1);
int out_r2_max = sgl_pow2(radius + 1);
uint8_t edge_alpha = 0;
sgl_area_t clip = SGL_AREA_MAX;
sgl_surf_clip_area_return(surf, area, &clip);
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
y2 = sgl_pow2(y - cy);
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
real_r2 = sgl_pow2(x - cx) + y2;
if (real_r2 >= out_r2_max) {
if (x > cx)
break;
continue;
}
if (real_r2 < in_r2_max) {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
continue;
}
if (real_r2 < in_r2 ) {
edge_alpha = sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(border_color, color, sgl_sqrt_error(real_r2)) : sgl_color_mixer(sgl_color_mixer(border_color, color, edge_alpha), *blend, alpha));
}
else if (real_r2 > out_r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(border_color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(border_color, *blend, edge_alpha), *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha));
}
}
buf += surf->w;
}
}
/**
* @brief draw task, the task contains the draw information and canvas
* @param surf surface pointer
* @param area the area of the task
* @param desc the draw information
* @return none
*/
void sgl_draw_circle(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_circle_t *desc)
{
sgl_color_t color = desc->color;
int16_t radius = desc->radius;
uint8_t alpha = desc->alpha;
uint16_t border = desc->border;
sgl_color_t border_color = desc->border_color;
if (unlikely(desc->alpha == SGL_ALPHA_MIN)) {
return;
}
if (desc->pixmap == NULL) {
if (border) {
sgl_draw_fill_circle_with_border(surf, area, desc->cx, desc->cy, radius, color, border_color, border, alpha);
}
else {
sgl_draw_fill_circle(surf, area, desc->cx, desc->cy, radius, color, alpha);
}
}
else {
sgl_draw_fill_circle_pixmap(surf, area, desc->cx, desc->cy, radius, desc->pixmap, alpha);
}
}

View File

@ -0,0 +1,79 @@
/* source/draw/sgl_draw_icon.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_log.h>
#include <sgl_draw.h>
#include <sgl_math.h>
/**
* @brief draw icon with alpha
* @param surf surface
* @param area area of icon
* @param coords coords of icon
* @param alpha alpha of icon
* @param icon icon pixmap
* @return none
* @note This function is only for 4bpp icon bitmap
*/
void sgl_draw_icon( sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, sgl_color_t color, uint8_t alpha, const sgl_icon_pixmap_t *icon)
{
const uint8_t *dot = icon->bitmap;
sgl_area_t clip = SGL_AREA_MAX;
sgl_color_t *buf = NULL;
int rel_x, rel_y, byte_x, dot_index;
uint8_t alpha_dot;
sgl_area_t icon_rect = {
.x1 = x,
.x2 = x + icon->width - 1,
.y1 = y,
.y2 = y + icon->height - 1,
};
if (!sgl_surf_clip(surf, &icon_rect, &clip)) {
return;
}
if (!sgl_area_selfclip(&clip, area)) {
return;
}
for (int y = clip.y1; y <= clip.y2; y++) {
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, y - surf->y1);
rel_y = y - icon_rect.y1;
for (int x = clip.x1; x <= clip.x2; x++) {
rel_x = x - icon_rect.x1;
byte_x = rel_x >> 1;
dot_index = byte_x + (rel_y * (icon->width >> 1));
alpha_dot = (rel_x & 1) ? dot[dot_index] & 0xF : (dot[dot_index] >> 4);
alpha_dot = alpha_dot | (alpha_dot << 4);
*buf = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(color, *buf, alpha_dot) : sgl_color_mixer(sgl_color_mixer(color, *buf, alpha_dot), *buf, alpha));
buf++;
}
}
}

View File

@ -0,0 +1,195 @@
/* source/draw/sgl_draw_line.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_log.h>
#include <sgl_draw.h>
#include <sgl_math.h>
/**
* @brief draw a horizontal line with alpha
* @param surf surface
* @param area area that contains the line
* @param y line y position
* @param x1 line start x position
* @param x2 line end x position
* @param color line color
* @param alpha alpha of color
* @return none
*/
void sgl_draw_fill_hline(sgl_surf_t *surf, sgl_area_t *area, int16_t y, int16_t x1, int16_t x2, uint8_t width, sgl_color_t color, uint8_t alpha)
{
sgl_color_t *buf = NULL, *blend = NULL;
sgl_area_t c_rect = {.x1 = x1, .x2 = x2, .y1 = y - (width - 1) / 2, .y2 = y + width / 2}, clip = SGL_AREA_MAX;
if (c_rect.x1 > c_rect.x2) {
sgl_swap(&c_rect.x1, &c_rect.x2);
}
sgl_surf_clip_area_return(surf, area, &clip);
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
*blend = alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha);
}
buf += surf->w;
}
}
/**
* @brief draw a vertical line with alpha
* @param surf surface
* @param area area that contains the line
* @param x x coordinate
* @param y1 y1 coordinate
* @param y2 y2 coordinate
* @param color line color
* @param alpha alpha of color
* @return none
*/
void sgl_draw_fill_vline(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y1, int16_t y2, uint8_t width, sgl_color_t color, uint8_t alpha)
{
sgl_color_t *buf = NULL, *blend = NULL;
sgl_area_t c_rect = {.x1 = x - (width - 1) / 2, .x2 = x + width / 2, .y1 = y1,.y2 = y2}, clip = SGL_AREA_MAX;
if (c_rect.y1 > c_rect.y2) {
sgl_swap(&c_rect.y1, &c_rect.y2);
}
sgl_surf_clip_area_return(surf, area, &clip);
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
}
buf += surf->w;
}
}
/**
* SDF draw anti-aliased line
* @param thickness line thickness (in pixels)
*/
static int32_t sgl_capsule_sdf_optimized(int16_t px, int16_t py, int16_t ax, int16_t ay, int16_t bx, int16_t by)
{
int64_t pax = px - ax, pay = py - ay, bax = bx - ax, bay = by - ay;
int64_t b_sqd = bax * bax + bay * bay;
int64_t h = (sgl_max(sgl_min((pax * bax + pay * bay), b_sqd), 0)) << 8;
int64_t dx = (pax << 8) - bax * h / b_sqd;
int64_t dy = (pay << 8) - bay * h / b_sqd;
return sgl_sqrt(dx * dx + dy * dy);
}
/**
* @brief draw a slanted line with alpha
* @param surf surface
* @param area area that contains the line
* @param x1 line start x position
* @param y1 line start y position
* @param x2 line end x position
* @param y2 line end y position
* @param thickness line width
* @param color line color
* @param alpha alpha of color
* @return none
* @note This algorithm is SDF algorithm
*/
void draw_line_fill_slanted(sgl_surf_t *surf, sgl_area_t *area, int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t thickness, sgl_color_t color, uint8_t alpha)
{
uint8_t c;
int64_t len;
sgl_area_t clip = SGL_AREA_MAX;
sgl_color_t *buf = NULL, *blend = NULL;
int16_t thick_half = (thickness >> 1);
sgl_area_t c_rect = {
.x1 = (x1 < x2 ? x1 : x2) - thick_half,
.x2 = (x1 > x2 ? x1 : x2) + thick_half,
.y1 = (y1 < y2 ? y1 : y2) - thick_half,
.y2 = (y1 > y2 ? y1 : y2) + thick_half,
};
sgl_surf_clip_area_return(surf, area, &clip);
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
len = sgl_capsule_sdf_optimized(x, y, x1, y1, x2, y2);
if (len <= (thick_half - 1) << 8) {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
continue;
}
if (len > ((thick_half - 1) << 8) && len < (thick_half << 8)) {
c = len - ((thick_half - 1) << 8);
if (alpha == SGL_ALPHA_MAX)
*blend = sgl_color_mixer(*blend, color, c);
else
*blend = sgl_color_mixer(sgl_color_mixer(*blend, color, c), *blend, alpha);
}
}
buf += surf->w;
}
}
/**
* @brief draw a line
* @param surf surface
* @param area area that contains the line
* @param desc line description
* @return none
*/
void sgl_draw_line(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_line_t *desc)
{
if (desc->x1 == desc->x2) {
sgl_draw_fill_vline(surf, area, desc->x1, desc->y1, desc->y2, desc->width / 2, desc->color, desc->alpha);
}
else if (desc->y1 == desc->y2) {
sgl_draw_fill_hline(surf, area, desc->y1, desc->x1, desc->x2, desc->width / 2, desc->color, desc->alpha);
}
else {
draw_line_fill_slanted(surf, area, desc->x1, desc->y1, desc->x2, desc->y2, desc->width, desc->color, desc->alpha);
}
}

View File

@ -0,0 +1,454 @@
/* source/draw/sgl_draw_rect.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
/**
* @brief fill a round rectangle with alpha
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param radius radius of round
* @param color color of rectangle
* @param alpha alpha of rectangle
* @return none
*/
void sgl_draw_fill_rect(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, sgl_color_t color, uint8_t alpha)
{
sgl_area_t clip;
sgl_color_t *buf = NULL, *blend = NULL;
uint8_t edge_alpha = 0;
int cx1 = rect->x1 + radius;
int cx2 = rect->x2 - radius;
int cy1 = rect->y1 + radius;
int cy2 = rect->y2 - radius;
int cx_tmp = 0;
int cy_tmp = 0;
if (!sgl_surf_clip(surf, area, &clip)) {
return;
}
if (!sgl_area_selfclip(&clip, rect)) {
return;
}
int y2 = 0, real_r2 = 0;
int r2 = sgl_pow2(radius);
int r2_edge = sgl_pow2(radius + 1);
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
if (radius == 0) {
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
*blend = alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha);
}
buf += surf->w;
}
}
else {
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
if (y > cy1 && y < cy2) {
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
}
}
else {
cy_tmp = y > cy1 ? cy2 : cy1;
y2 = sgl_pow2(y - cy_tmp);
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
if (x > cx1 && x < cx2) {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
}
else {
cx_tmp = x > cx1 ? cx2 : cx1;
real_r2 = sgl_pow2(x - cx_tmp) + y2;
if (real_r2 >= r2_edge) {
continue;
}
else if (real_r2 >= r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(color, *blend, edge_alpha), *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
}
}
}
}
buf += surf->w;
}
}
}
#include <math.h>
/**
* @brief fill a round rectangle with alpha and border
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param radius radius of round
* @param color color of rectangle
* @param border_color color of border
* @param border_width width of border
* @param alpha alpha of rectangle
* @return none
*/
void sgl_draw_fill_rect_with_border(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, sgl_color_t color, sgl_color_t border_color, uint8_t border_width, uint8_t alpha)
{
int radius_in = sgl_max(radius - border_width + 1, 0);
int y2 = 0, real_r2 = 0;
int in_r2 = sgl_pow2(radius_in);
int out_r2 = sgl_pow2(radius);
sgl_color_t *buf = NULL, *blend = NULL;
uint8_t edge_alpha = 0;
int cx1 = rect->x1 + radius;
int cx2 = rect->x2 - radius;
int cy1 = rect->y1 + radius;
int cy2 = rect->y2 - radius;
int cx1i = rect->x1 + border_width;
int cx2i = rect->x2 - border_width;
int cyi1 = rect->y1 + border_width;
int cyi2 = rect->y2 - border_width;
int cx_tmp = 0;
int cy_tmp = 0;
int in_r2_max = sgl_pow2(radius_in - 1);
int out_r2_max = sgl_pow2(radius + 1);
sgl_area_t clip;
if (!sgl_surf_clip(surf, area, &clip)) {
return;
}
if (!sgl_area_selfclip(&clip, rect)) {
return;
}
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
if (radius == 0) {
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
if (x >= cx1i && x <= cx2i && y >= cyi1 && y <= cyi2) {
*blend = alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha);
}
else {
*blend = alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha);
}
}
buf += surf->w;
}
}
else {
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
if (y > cy1 && y < cy2) {
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
if (x < cx1i || x > cx2i) {
*blend = (alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? color: sgl_color_mixer(color, *blend, alpha));
}
}
}
else {
cy_tmp = y > cy1 ? cy2 : cy1;
y2 = sgl_pow2(y - cy_tmp);
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
if (x >= cx1 && x <= cx2) {
if (y < cyi1 || y > cyi2) {
*blend = (alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
}
}
else {
cx_tmp = x > cx1 ? cx2 : cx1;
real_r2 = sgl_pow2(x - cx_tmp) + y2;
if (real_r2 >= out_r2_max) {
continue;
}
if (real_r2 < in_r2_max) {
*blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha));
continue;
}
if (real_r2 < in_r2 ) {
edge_alpha = sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(border_color, color, edge_alpha) : sgl_color_mixer(sgl_color_mixer(border_color, color, edge_alpha), *blend, alpha));
}
else if (real_r2 > out_r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(border_color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(border_color, *blend, edge_alpha), *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha));
}
}
}
}
buf += surf->w;
}
}
}
#if (!CONFIG_SGL_PIXMAP_BILINEAR_INTERP)
/**
* @brief fill a round rectangle pixmap with alpha
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param radius radius of round
* @param pixmap pixmap of rectangle
* @param alpha alpha of rectangle
* @return none
*/
void sgl_draw_fill_rect_pixmap(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha)
{
sgl_area_t clip;
sgl_color_t *buf = NULL, *blend = NULL;
sgl_color_t *pbuf = NULL;
uint8_t edge_alpha = 0;
int cx1 = rect->x1 + radius;
int cx2 = rect->x2 - radius;
int cy1 = rect->y1 + radius;
int cy2 = rect->y2 - radius;
int cx_tmp = 0;
int cy_tmp = 0;
if (!sgl_surf_clip(surf, area, &clip)) {
return;
}
if (!sgl_area_selfclip(&clip, rect)) {
return;
}
int y2 = 0, real_r2 = 0;
int r2 = sgl_pow2(radius);
int r2_edge = sgl_pow2(radius + 1);
uint32_t scale_x = ((pixmap->width << SGL_FIXED_SHIFT) / (rect->x2 - rect->x1 + 1));
uint32_t scale_y = ((pixmap->height << SGL_FIXED_SHIFT) / (rect->y2 - rect->y1 + 1));
uint32_t step_x = 0, step_y = 0;
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
if (radius == 0) {
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
step_y = (scale_y * (y - rect->y1)) >> SGL_FIXED_SHIFT;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
step_x = (scale_x * (x - rect->x1)) >> SGL_FIXED_SHIFT;
pbuf = sgl_pixmap_get_buf(pixmap, step_x, step_y);
*blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha));
}
buf += surf->w;
}
}
else {
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
step_y = (scale_y * (y - rect->y1)) >> SGL_FIXED_SHIFT;
if (y > cy1 && y < cy2) {
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
step_x = (scale_x * (x - rect->x1)) >> SGL_FIXED_SHIFT;
pbuf = sgl_pixmap_get_buf(pixmap, step_x, step_y);
*blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha));
}
}
else {
cy_tmp = y > cy1 ? cy2 : cy1;
y2 = sgl_pow2(y - cy_tmp);
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
step_x = (scale_x * (x - rect->x1)) >> SGL_FIXED_SHIFT;
pbuf = sgl_pixmap_get_buf(pixmap, step_x, step_y);
if (x > cx1 && x < cx2) {
*blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha));
}
else {
cx_tmp = x > cx1 ? cx2 : cx1;
real_r2 = sgl_pow2(x - cx_tmp) + y2;
if (real_r2 >= r2_edge) {
continue;
}
else if (real_r2 >= r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(*pbuf, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(*pbuf, *blend, edge_alpha), *blend, alpha));
}
else {
*blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha));
}
}
}
}
buf += surf->w;
}
}
}
#else
/**
* @brief fill a round rectangle pixmap with alpha
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param radius radius of round
* @param pixmap pixmap of rectangle
* @param alpha alpha of rectangle
* @return none
*/
void sgl_draw_fill_rect_pixmap(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha)
{
sgl_area_t clip;
sgl_color_t *buf = NULL, *blend = NULL, *pix = (sgl_color_t *)pixmap->bitmap.array;
sgl_color_t ip_color;
uint8_t edge_alpha = 0;
int cx1 = rect->x1 + radius;
int cx2 = rect->x2 - radius;
int cy1 = rect->y1 + radius;
int cy2 = rect->y2 - radius;
int cx_tmp = 0, fx = 0;
int cy_tmp = 0, fy = 0;
if (!sgl_surf_clip(surf, area, &clip)) {
return;
}
if (!sgl_area_selfclip(&clip, rect)) {
return;
}
int y2 = 0, real_r2 = 0;
int r2 = sgl_pow2(radius);
int r2_edge = sgl_pow2(radius + 1);
const int32_t rect_w = rect->x2 - rect->x1 + 1;
const int32_t rect_h = rect->y2 - rect->y1 + 1;
const int32_t scale_x = ((int32_t)pixmap->width << SGL_FIXED_SHIFT) / rect_w;
const int32_t scale_y = ((int32_t)pixmap->height << SGL_FIXED_SHIFT) / rect_h;
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
if (radius == 0) {
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
fy = (int32_t)(y - rect->y1) * scale_y;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
fx = (int32_t)(x - rect->x1) * scale_x;
ip_color = sgl_draw_biln_color(pix, pixmap->width, pixmap->height, fx, fy);
*blend = (alpha == SGL_ALPHA_MAX) ? ip_color : sgl_color_mixer(ip_color, *blend, alpha);
}
buf += surf->w;
}
}
else {
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
fy = (int32_t)(y - rect->y1) * scale_y;
if (y > cy1 && y < cy2) {
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
fx = (int32_t)(x - rect->x1) * scale_x;
ip_color = sgl_draw_biln_color(pix, pixmap->width, pixmap->height, fx, fy);
*blend = (alpha == SGL_ALPHA_MAX) ? ip_color : sgl_color_mixer(ip_color, *blend, alpha);
}
}
else {
cy_tmp = y > cy1 ? cy2 : cy1;
y2 = sgl_pow2(y - cy_tmp);
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
fx = (int32_t)(x - rect->x1) * scale_x;
ip_color = sgl_draw_biln_color(pix, pixmap->width, pixmap->height, fx, fy);
if (x > cx1 && x < cx2) {
*blend = (alpha == SGL_ALPHA_MAX) ? ip_color : sgl_color_mixer(ip_color, *blend, alpha);
}
else {
cx_tmp = x > cx1 ? cx2 : cx1;
real_r2 = sgl_pow2(x - cx_tmp) + y2;
if (real_r2 >= r2_edge) {
continue;
}
else if (real_r2 >= r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
*blend = (alpha == SGL_ALPHA_MAX) ? sgl_color_mixer(ip_color, *blend, edge_alpha) :
sgl_color_mixer(sgl_color_mixer(ip_color, *blend, edge_alpha), *blend, alpha);
}
else {
*blend = (alpha == SGL_ALPHA_MAX) ? ip_color : sgl_color_mixer(ip_color, *blend, alpha);
}
}
}
}
buf += surf->w;
}
}
}
#endif
/**
* @brief fill a round rectangle with alpha
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param desc rectangle description
* @return none
*/
void sgl_draw_rect(sgl_surf_t *surf, sgl_area_t *area, sgl_rect_t *rect, sgl_draw_rect_t *desc)
{
if (unlikely(desc->alpha == SGL_ALPHA_MIN)) {
return;
}
if (desc->pixmap == NULL) {
if (desc->border == 0) {
sgl_draw_fill_rect(surf, area, rect, desc->radius, desc->color, desc->alpha);
}
else {
sgl_draw_fill_rect_with_border(surf, area, rect, desc->radius, desc->color, desc->border_color, desc->border, desc->alpha);
}
}
else {
sgl_draw_fill_rect_pixmap(surf, area, rect, desc->radius, desc->pixmap, desc->alpha);
}
}

View File

@ -0,0 +1,110 @@
/* source/draw/sgl_draw_ring.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
/**
* @brief draw a ring on surface with alpha
* @param surf: pointer of surface
* @param area: pointer of area
* @param cx: ring center x
* @param cy: ring center y
* @param radius_in: ring inner radius
* @param radius_out: ring outer radius
* @param color: ring color
* @param alpha: ring alpha
* @return none
*/
void sgl_draw_fill_ring(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius_in, int16_t radius_out, sgl_color_t color, uint8_t alpha)
{
int y2 = 0, real_r2 = 0, edge_alpha = 0;
int in_r2 = sgl_pow2(radius_in);
int out_r2 = sgl_pow2(radius_out);
int in_r2_max = sgl_pow2(radius_in - 1);
int out_r2_max = sgl_pow2(radius_out + 1);
sgl_color_t *buf = NULL, *blend = NULL;
sgl_area_t clip;
if (unlikely(alpha == SGL_ALPHA_MIN)) {
return;
}
if (!sgl_surf_clip(surf, area, &clip)) {
return;
}
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
y2 = sgl_pow2(y - cy);
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
real_r2 = sgl_pow2(x - cx) + y2;
if (real_r2 >= out_r2_max) {
if (x > cx) break;
continue;
}
if (real_r2 < in_r2_max) {
if (x < cx) {
blend += ((cx - x) * 2);
x = cx*2 - x;
}
continue;
}
if (alpha == SGL_ALPHA_MAX) {
if (real_r2 < in_r2 ) {
*blend = sgl_color_mixer(color, *blend, sgl_sqrt_error(real_r2));
}
else if (real_r2 > out_r2) {
*blend = sgl_color_mixer(color, *blend, SGL_ALPHA_MAX - sgl_sqrt_error(real_r2));
}
else {
*blend = color;
}
}
else {
if (real_r2 < in_r2 ) {
edge_alpha = sgl_sqrt_error(real_r2);
sgl_color_t color_mix = sgl_color_mixer(color, *blend, edge_alpha);
*blend = sgl_color_mixer(color_mix, *blend, alpha);
}
else if (real_r2 > out_r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
sgl_color_t color_mix = sgl_color_mixer(color, *blend, edge_alpha);
*blend = sgl_color_mixer(color_mix, *blend, alpha);
}
else {
*blend = sgl_color_mixer(color, *blend, alpha);
}
}
}
buf += surf->w;
}
}

View File

@ -0,0 +1,357 @@
/* source/draw/sgl_draw_text.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_log.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#if (CONFIG_SGL_FONT_COMPRESSED)
/**
* @brief RLE state, refrence LVGL
*/
typedef enum {
RLE_STATE_SINGLE = 0,
RLE_STATE_REPEATED,
RLE_STATE_COUNTER,
} sgl_font_rle_state_t;
/**
* @brief RLE decompress information structure
*/
typedef struct {
uint32_t rdp;
const uint8_t * in;
uint8_t bpp;
uint8_t prev_v;
uint8_t count;
sgl_font_rle_state_t state;
} sgl_font_rle_t;
static sgl_font_rle_t font_rle = {
.rdp = 0,
.in = NULL,
.bpp = 0,
.prev_v = 0,
.count = 0,
.state = RLE_STATE_SINGLE,
};
/**
* @brief Get bits from a byte array
* @param in the byte array
* @param bit_pos the bit position
* @param len the bit length
* @return the bits of a byte
*/
static inline uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len)
{
uint8_t bit_mask;
switch(len) {
case 1:
bit_mask = 0x1;
break;
case 2:
bit_mask = 0x3;
break;
case 4:
bit_mask = 0xF;
break;
default:
bit_mask = (uint16_t)((uint16_t) 1 << len) - 1;
}
uint32_t byte_pos = bit_pos >> 3;
bit_pos = bit_pos & 0x7;
if(bit_pos + len >= 8) {
uint16_t in16 = (in[byte_pos] << 8) + in[byte_pos + 1];
return (in16 >> (16 - bit_pos - len)) & bit_mask;
}
else {
return (in[byte_pos] >> (8 - bit_pos - len)) & bit_mask;
}
}
/**
* @brief Decompress a line of RLE data
* @param out the decompressed data
* @param w the width of the decompressed data
* @return none
*/
static inline void decompress_line(uint8_t *out, int32_t w)
{
int32_t i;
uint8_t v = 0;
uint8_t ret = 0;
sgl_font_rle_t *rle = &font_rle;
for(i = 0; i < w; i++) {
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_REPEATED;
}
rle->prev_v = ret;
rle->rdp += rle->bpp;
}
else if(rle->state == RLE_STATE_REPEATED) {
v = get_bits(rle->in, rle->rdp, 1);
rle->count++;
rle->rdp += 1;
if(v == 1) {
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;
}
}
}
else {
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;
}
}
if (out != NULL) {
out[i] = ret;
}
}
}
/**
* @brief Initialize the RLE decompression state
* @param in Pointer to the input data
* @param bpp Bits per pixel of the input data
* @return none
*/
static inline void font_rle_init(const uint8_t * in, uint8_t bpp)
{
font_rle.in = in;
font_rle.bpp = bpp;
font_rle.state = RLE_STATE_SINGLE;
font_rle.rdp = 0;
font_rle.prev_v = 0;
font_rle.count = 0;
}
#endif // (!CONFIG_SGL_FONT_COMPRESSED)
/**
* @brief Draw a character on the surface with alpha blending
* @param surf Pointer to the surface where the character will be drawn
* @param area Pointer to the area where the character will be drawn
* @param x X coordinate where the character will be drawn
* @param y Y coordinate where the character will be drawn
* @param ch_index Index of the character in the font table
* @param color Foreground color of the character
* @param alpha Alpha value for blending
* @param font Pointer to the font structure containing character data
* @return none
* @note this function is only support bpp:4
*/
void sgl_draw_character(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, uint32_t ch_index, sgl_color_t color, uint8_t alpha, const sgl_font_t *font)
{
int offset_y2 = font->font_height - font->table[ch_index].ofs_y - font->base_line;
const uint8_t *dot = &font->bitmap[font->table[ch_index].bitmap_index];
const uint8_t font_w = font->table[ch_index].box_w;
const uint8_t font_h = font->table[ch_index].box_h;
uint8_t shift = 0;
uint32_t pixel_index, rel_x, rel_y;
uint16_t byte_index, alpha_dot = 0;
sgl_color_t color_mix, *buf = NULL, *blend = NULL;
sgl_area_t clip;
sgl_area_t text_rect = {
.x1 = x + font->table[ch_index].ofs_x,
.x2 = x + font->table[ch_index].ofs_x + font_w - 1,
.y1 = y + offset_y2 - font_h,
.y2 = y + offset_y2 - 1,
};
if (!sgl_surf_clip(surf, &text_rect, &clip)) {
return;
}
if (!sgl_area_selfclip(&clip, area)) {
return;
}
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
#if (CONFIG_SGL_FONT_COMPRESSED)
if (font->compress == 0) {
#endif // (!CONFIG_SGL_FONT_COMPRESSED == 0)
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
rel_y = y - text_rect.y1;
for (int x = clip.x1; x <= clip.x2; x++) {
rel_x = x - text_rect.x1;
pixel_index = rel_y * font_w + rel_x;
if (font->bpp == 4) {
byte_index = pixel_index >> 1;
alpha_dot = sgl_opa4_table[(pixel_index & 1) ? (dot[byte_index] & 0x0F) : (dot[byte_index] >> 4)];
}
else if (font->bpp == 2) {
byte_index = pixel_index >> 2;
shift = (3 - (pixel_index & 0x3)) * 2;
alpha_dot = sgl_opa2_table[(dot[byte_index] >> shift) & 0x03];
}
else if (font->bpp == 1) {
byte_index = pixel_index >> 3;
shift = 7 - (pixel_index & 0x7);
alpha_dot = ((dot[byte_index] >> shift) & 0x01) ? SGL_ALPHA_MAX : SGL_ALPHA_MIN;
}
color_mix = sgl_color_mixer(color, *blend, alpha_dot);
*blend = sgl_color_mixer(color_mix, *blend, alpha);
blend++;
}
buf += surf->w;
}
#if (CONFIG_SGL_FONT_COMPRESSED)
} /* support compressed font */
else {
uint8_t line_buf[128] = {0};
font_rle_init(dot, font->bpp);
for (int y = text_rect.y1; y < clip.y1; y++) {
decompress_line(NULL, font_w);
}
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
decompress_line(line_buf, font_w);
for (int x = clip.x1; x <= clip.x2; x++) {
if (font->bpp == 4) {
color_mix = sgl_color_mixer(color, *blend, sgl_opa4_table[line_buf[x - text_rect.x1]]);
}
else if (font->bpp == 2) {
color_mix = sgl_color_mixer(color, *blend, sgl_opa2_table[line_buf[x - text_rect.x1]]);
}
else if (font->bpp == 1) {
color_mix = sgl_color_mixer(color, *blend, line_buf[x - text_rect.x1] ? SGL_ALPHA_MAX : SGL_ALPHA_MIN);
}
*blend = sgl_color_mixer(color_mix, *blend, alpha);
blend++;
}
buf += surf->w;
}
}
#endif
}
/**
* @brief Draw a string on the surface with alpha blending
* @param surf Pointer to the surface where the string will be drawn
* @param area Pointer to the area where the string will be drawn
* @param x X coordinate of the top-left corner of the string
* @param y Y coordinate of the top-left corner of the string
* @param str Pointer to the string to be drawn
* @param color Foreground color of the string
* @param alpha Alpha value for blending
* @param font Pointer to the font structure containing character data
* @return none
*/
void sgl_draw_string(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, const char *str, sgl_color_t color, uint8_t alpha, const sgl_font_t *font)
{
uint32_t ch_index;
uint32_t unicode = 0;
while (*str) {
str += sgl_utf8_to_unicode(str, &unicode);
ch_index = sgl_search_unicode_ch_index(font, unicode);
sgl_draw_character(surf, area, x, y, ch_index, color, alpha, font);
x += (font->table[ch_index].adv_w >> 4);
}
}
/**
* @brief Draw a string on the surface with alpha blending and multiple lines
* @param surf Pointer to the surface where the string will be drawn
* @param area Pointer to the area where the string will be drawn
* @param x X coordinate of the top-left corner of the string
* @param y Y coordinate of the top-left corner of the string
* @param str Pointer to the string to be drawn
* @param color Foreground color of the string
* @param alpha Alpha value for blending
* @param font Pointer to the font structure containing character data
* @param line_margin Margin between lines
* @return none
*/
void sgl_draw_string_mult_line(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, const char *str, sgl_color_t color, uint8_t alpha, const sgl_font_t *font, uint8_t line_margin)
{
int16_t ch_index, ch_width;
int16_t x_off = x;
uint32_t unicode = 0;
while (*str) {
if (*str == '\n') {
x_off = x;
y += (font->font_height + line_margin);
str ++;
continue;
}
str += sgl_utf8_to_unicode(str, &unicode);
ch_index = sgl_search_unicode_ch_index(font, unicode);
ch_width = (font->table[ch_index].adv_w >> 4);
if ((x_off + ch_width) > area->x2) {
x_off = x;
y += (font->font_height + line_margin);
}
sgl_draw_character(surf, area, x_off, y, ch_index, color, alpha, font);
x_off += ch_width;
}
}

View File

@ -0,0 +1,157 @@
/* source/draw/sgl_draw_xform.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_log.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <string.h>
/**
* @brief calculate a point color by bilinear interpolate
* @param buffer point to image pixmap start buffer
* @param w width of buffer
* @param h height of buffer
* @param fx x coordinate of point
* @param fy y coordinate of point
* @return point color
*/
sgl_color_t sgl_draw_biln_color(const sgl_color_t *buffer, int16_t w, int16_t h, int32_t fx, int32_t fy)
{
sgl_color_t ret;
int32_t max_x = (((int32_t)w) - 1) << SGL_FIXED_SHIFT;
int32_t max_y = (((int32_t)h) - 1) << SGL_FIXED_SHIFT;
fx = fx < 0 ? 0 : (fx > max_x ? max_x : fx);
fy = fy < 0 ? 0 : (fy > max_y ? max_y : fy);
const int32_t x0 = fx >> SGL_FIXED_SHIFT;
const int32_t y0 = fy >> SGL_FIXED_SHIFT;
const int32_t dx = fx & SGL_FIXED_MASK;
const int32_t dy = fy & SGL_FIXED_MASK;
const int32_t dx1 = SGL_FIXED_ONE - dx;
const int32_t dy1 = SGL_FIXED_ONE - dy;
const int32_t point = (y0 * w) + x0;
const sgl_color_t p00 = buffer[point];
const sgl_color_t p01 = buffer[point + 1];
const sgl_color_t p10 = buffer[point + w];
const sgl_color_t p11 = buffer[point + w + 1];
const uint8_t r00 = p00.ch.red;
const uint8_t r01 = p01.ch.red;
const uint8_t r10 = p10.ch.red;
const uint8_t r11 = p11.ch.red;
const uint8_t g00 = p00.ch.green;
const uint8_t g01 = p01.ch.green;
const uint8_t g10 = p10.ch.green;
const uint8_t g11 = p11.ch.green;
const uint8_t b00 = p00.ch.blue;
const uint8_t b01 = p01.ch.blue;
const uint8_t b10 = p10.ch.blue;
const uint8_t b11 = p11.ch.blue;
ret.ch.red = ((r00 * dx1 * dy1) + (r01 * dx * dy1) + (r10 * dx1 * dy) + (r11 * dx * dy)) >> (2 * SGL_FIXED_SHIFT);
ret.ch.green = ((g00 * dx1 * dy1) + (g01 * dx * dy1) + (g10 * dx1 * dy) + (g11 * dx * dy)) >> (2 * SGL_FIXED_SHIFT);
ret.ch.blue = ((b00 * dx1 * dy1) + (b01 * dx * dy1) + (b10 * dx1 * dy) + (b11 * dx * dy)) >> (2 * SGL_FIXED_SHIFT);
return ret;
}
/**
* @brief transform a surface
* @param dst destination surface
* @param src source surface
* @param area area of surface
* @param x x coordinate of surface
* @param y y coordinate of surface
* @param rotation rotation angle
* @return none
* @note This function has implemented angle normalization to the range of 0 to 360 degrees.
*/
void sgl_draw_xform_surf(sgl_surf_t *dst, sgl_surf_t *src, sgl_area_t *area, int16_t x, int16_t y, int16_t rotation)
{
const int32_t sin_val = sgl_sin(rotation);
const int32_t cos_val = sgl_cos(rotation);
const int16_t half_w = src->w / 2;
const int16_t half_h = src->h / 2;
const int16_t x1r = (cos_val * (-half_w) - sin_val * (-half_h)) / SGL_SIN_FIXED_ONE;
const int16_t y1r = (sin_val * (-half_w) + cos_val * (-half_h)) / SGL_SIN_FIXED_ONE;
const int16_t x2r = (cos_val * half_w - sin_val * (-half_h)) / SGL_SIN_FIXED_ONE;
const int16_t y2r = (sin_val * half_w + cos_val * (-half_h)) / SGL_SIN_FIXED_ONE;
const int16_t x3r = (cos_val * half_w - sin_val * half_h) / SGL_SIN_FIXED_ONE;
const int16_t y3r = (sin_val * half_w + cos_val * half_h) / SGL_SIN_FIXED_ONE;
const int16_t x4r = (cos_val * (-half_w) - sin_val * half_h) / SGL_SIN_FIXED_ONE;
const int16_t y4r = (sin_val * (-half_w) + cos_val * half_h) / SGL_SIN_FIXED_ONE;
const int16_t min_x = sgl_min4(x1r, x2r, x3r, x4r);
const int16_t min_y = sgl_min4(y1r, y2r, y3r, y4r);
const int16_t max_x = sgl_max4(x1r, x2r, x3r, x4r);
const int16_t max_y = sgl_max4(y1r, y2r, y3r, y4r);
const int16_t center_x = x + half_w;
const int16_t center_y = y + half_h;
const int16_t buf_width = src->w > 0 ? src->w : 1;
const int16_t buf_height = src->h > 0 ? src->h : 1;
const int16_t buf_size = buf_width * buf_height;
if (buf_size <= 0 || src->w <= 0) {
return;
}
for (int py = (int)min_y; py <= max_y; py++) {
for (int px = (int)min_x; px <= max_x; px++) {
int rel_x = px;
int rel_y = py;
int32_t orig_x_fixed = cos_val * rel_x + sin_val * rel_y;
int32_t orig_y_fixed = -sin_val * rel_x + cos_val * rel_y;
const int orig_x = (orig_x_fixed / SGL_SIN_FIXED_ONE) + half_w;
const int orig_y = (orig_y_fixed / SGL_SIN_FIXED_ONE) + half_h;
if (orig_x >= 0 && orig_x < buf_width && orig_y >= 0 && orig_y < buf_height) {
int src_idx = orig_y * buf_width + orig_x;
const int dst_x = center_x + px;
const int dst_y = center_y + py;
if (dst_x >= area->x1 && dst_x <= area->x2 && dst_y >= area->y1 && dst_y <= area->y2
&& dst_x >= dst->x1 && dst_x <= dst->x2 && dst_y >= dst->y1 && dst_y <= dst->y2
) {
int dst_idx = (dst_y - dst->y1) * dst->w + (dst_x - dst->x1);
dst->buffer[dst_idx] = src->buffer[src_idx];
}
}
}
}
}

View File

@ -0,0 +1,64 @@
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
if(SGL_FONT_SONG23)
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_song23.c
)
endif()
if(SGL_FONT_CONSOLAS14)
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas14.c
)
endif()
if(SGL_FONT_CONSOLAS23)
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas23.c
)
endif()
if(SGL_FONT_CONSOLAS24)
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas24.c
)
endif()
if(SGL_FONT_CONSOLAS32)
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas34.c
)
endif()
if(CONFIG_SGL_FONT_CONSOLAS24_COMPRESS)
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas24_compress.c
)
endif()

View File

@ -0,0 +1,55 @@
# source/fonts/lm.cfg
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
CONFIG_SGL_FONT_SONG23
choices = n, y
default = n
CONFIG_SGL_FONT_CONSOLAS14
choices = n, y
default = n
CONFIG_SGL_FONT_CONSOLAS23
choices = n, y
default = n
CONFIG_SGL_FONT_CONSOLAS24
choices = n, y
default = n
CONFIG_SGL_FONT_CONSOLAS32
choices = n, y
default = n
CONFIG_SGL_FONT_CONSOLAS24_COMPRESS
choices = n, y
default = n
depends = CONFIG_SGL_FONT_COMPRESSED
SRC-$(CONFIG_SGL_FONT_SONG23) += sgl_ascii_song23.c
SRC-$(CONFIG_SGL_FONT_CONSOLAS14) += sgl_ascii_consolas14.c
SRC-$(CONFIG_SGL_FONT_CONSOLAS23) += sgl_ascii_consolas23.c
SRC-$(CONFIG_SGL_FONT_CONSOLAS24) += sgl_ascii_consolas24.c
SRC-$(CONFIG_SGL_FONT_CONSOLAS32) += sgl_ascii_consolas34.c
SRC-$(CONFIG_SGL_FONT_CONSOLAS24_COMPRESS) += sgl_ascii_consolas24_compress.c

View File

@ -0,0 +1,662 @@
/* source/fonts/sgl_ascii_consolas14.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_font.h>
#if (CONFIG_SGL_FONT_CONSOLAS14)
static const uint8_t sgl_ascii_consolas14_bitmap[] = {
/* U+0020 " " */
/* U+0021 "!" */
0x5e, 0x4, 0xd0, 0x4d, 0x3, 0xc0, 0x3c, 0x2,
0x90, 0x26, 0x5, 0xe0,
/* U+0022 "\"" */
0x7c, 0x2f, 0x6, 0xb1, 0xf0, 0x47, 0xb, 0x0,
/* U+0023 "#" */
0x0, 0xd0, 0xa3, 0x0, 0x1c, 0xb, 0x20, 0x5d,
0xec, 0xfc, 0x40, 0x49, 0xd, 0x0, 0x5, 0x70,
0xd0, 0x9, 0xdd, 0xcf, 0xc0, 0x9, 0x43, 0xa0,
0x0, 0xa3, 0x49, 0x0,
/* U+0024 "$" */
0x0, 0x1, 0x0, 0x0, 0x9, 0x30, 0x6, 0xdf,
0xe4, 0x2e, 0x2d, 0x0, 0x3e, 0x1d, 0x0, 0x8,
0xfd, 0x10, 0x0, 0x5d, 0xe4, 0x0, 0x67, 0x5c,
0x11, 0x87, 0x9b, 0x4e, 0xff, 0xb1, 0x0, 0xc1,
0x0, 0x0, 0x40, 0x0,
/* U+0025 "%" */
0x5b, 0xc1, 0xc, 0x2b, 0x39, 0x47, 0x70, 0x3b,
0x83, 0xc0, 0x0, 0x0, 0xc2, 0x0, 0x0, 0x89,
0xba, 0x0, 0x3b, 0xa3, 0x94, 0xc, 0x2b, 0x28,
0x48, 0x60, 0x4c, 0xb0,
/* U+0026 "&" */
0x5, 0xde, 0x60, 0x0, 0xe2, 0x3e, 0x0, 0xd,
0x46, 0xb0, 0x0, 0x7f, 0xa0, 0x0, 0x3d, 0xac,
0x1f, 0x9, 0x70, 0xbc, 0xc0, 0x89, 0x1, 0xf9,
0x1, 0xbd, 0xc8, 0xe3,
/* U+0027 "'" */
0x5e, 0x4d, 0x29,
/* U+0028 "(" */
0x0, 0x7, 0x0, 0xa, 0x80, 0x4, 0xc0, 0x0,
0xc4, 0x0, 0x1f, 0x0, 0x3, 0xd0, 0x0, 0x2d,
0x0, 0x0, 0xf1, 0x0, 0xa, 0x60, 0x0, 0x2e,
0x10, 0x0, 0x6c, 0x0, 0x0, 0x30,
/* U+0029 ")" */
0x25, 0x0, 0x1d, 0x40, 0x3, 0xd0, 0x0, 0xb6,
0x0, 0x6a, 0x0, 0x3c, 0x0, 0x4c, 0x0, 0x79,
0x0, 0xc4, 0x5, 0xb0, 0x2d, 0x10, 0x2, 0x0,
/* U+002A "*" */
0x0, 0x1a, 0x0, 0xa, 0x5a, 0x96, 0x0, 0xbf,
0x50, 0xa, 0x5a, 0x95, 0x0, 0x1a, 0x0,
/* U+002B "+" */
0x0, 0x3c, 0x0, 0x0, 0x3, 0xc0, 0x0, 0x7e,
0xef, 0xee, 0x10, 0x3, 0xc0, 0x0, 0x0, 0x3c,
0x0, 0x0, 0x2, 0x80, 0x0,
/* U+002C "," */
0x0, 0x0, 0x8, 0xe1, 0x4, 0xf2, 0x4, 0xe0,
0x7a, 0x20,
/* U+002D "-" */
0x7f, 0xff, 0x0,
/* U+002E "." */
0x7d, 0x18, 0xe1,
/* U+002F "/" */
0x0, 0x0, 0xc, 0x20, 0x0, 0x7, 0x70, 0x0,
0x3, 0xc0, 0x0, 0x0, 0xc2, 0x0, 0x0, 0x87,
0x0, 0x0, 0x3b, 0x0, 0x0, 0xc, 0x20, 0x0,
0x8, 0x60, 0x0, 0x0,
/* U+0030 "0" */
0x3, 0xde, 0xb1, 0x0, 0xe3, 0x9, 0x90, 0x4b,
0x0, 0x9e, 0x6, 0x91, 0xca, 0xf0, 0x7c, 0xe6,
0xf, 0x5, 0xe2, 0x2, 0xe0, 0xe, 0x30, 0x98,
0x0, 0x4d, 0xea, 0x0,
/* U+0031 "1" */
0x1, 0x9f, 0x20, 0xe, 0x7f, 0x20, 0x1, 0xf,
0x20, 0x0, 0xf, 0x20, 0x0, 0xf, 0x20, 0x0,
0xf, 0x20, 0x0, 0xf, 0x20, 0xe, 0xff, 0xfc,
/* U+0032 "2" */
0x6, 0xee, 0x90, 0x7, 0x10, 0xd5, 0x0, 0x0,
0xa7, 0x0, 0x0, 0xe3, 0x0, 0xa, 0x90, 0x0,
0x9a, 0x0, 0x9, 0xb0, 0x0, 0x2f, 0xff, 0xfe,
/* U+0033 "3" */
0xa, 0xee, 0xa0, 0x0, 0x0, 0xd5, 0x0, 0x1,
0xd2, 0x1, 0xdf, 0xa0, 0x0, 0x0, 0xb8, 0x0,
0x0, 0x5b, 0x0, 0x0, 0xb6, 0xe, 0xed, 0x70,
/* U+0034 "4" */
0x0, 0xc, 0xf0, 0x0, 0x7, 0xaf, 0x0, 0x2,
0xd1, 0xf0, 0x0, 0xb4, 0x1f, 0x0, 0x6a, 0x1,
0xf0, 0xb, 0xee, 0xef, 0xe3, 0x0, 0x1, 0xf0,
0x0, 0x0, 0x1f, 0x0,
/* U+0035 "5" */
0xde, 0xee, 0x4d, 0x20, 0x0, 0xd2, 0x0, 0xc,
0xed, 0x90, 0x0, 0x1b, 0x80, 0x0, 0x6a, 0x0,
0x1c, 0x5e, 0xed, 0x60,
/* U+0036 "6" */
0x0, 0x7d, 0xe5, 0x8, 0xa1, 0x0, 0xe, 0x0,
0x0, 0x3e, 0xbc, 0xb2, 0x4d, 0x10, 0x6c, 0x2d,
0x0, 0x1f, 0xe, 0x30, 0x6b, 0x3, 0xdd, 0xb1,
/* U+0037 "7" */
0x4f, 0xff, 0xfd, 0x0, 0x0, 0x69, 0x0, 0x0,
0xe2, 0x0, 0x6, 0xb0, 0x0, 0xd, 0x30, 0x0,
0x5c, 0x0, 0x0, 0xc5, 0x0, 0x4, 0xd0, 0x0,
/* U+0038 "8" */
0x5, 0xdd, 0xc2, 0xf, 0x10, 0x7a, 0xf, 0x30,
0x89, 0x5, 0xec, 0xb0, 0x8, 0xc8, 0xe4, 0x2e,
0x0, 0x6d, 0x3e, 0x10, 0x6c, 0x7, 0xdd, 0xc2,
/* U+0039 "9" */
0x5, 0xdd, 0x90, 0x2e, 0x10, 0xa7, 0x5b, 0x0,
0x4c, 0x3e, 0x10, 0x6d, 0x7, 0xdc, 0xbc, 0x0,
0x0, 0x69, 0x0, 0x4, 0xe2, 0xd, 0xeb, 0x30,
/* U+003A ":" */
0x6e, 0x14, 0xb0, 0x0, 0x0, 0x0, 0x4b, 0x6,
0xe1,
/* U+003B ";" */
0x6, 0xe1, 0x4, 0xb0, 0x0, 0x0, 0x0, 0x0,
0x5, 0xd1, 0x3, 0xf3, 0x3, 0xe1, 0x6b, 0x30,
/* U+003C "<" */
0x0, 0x0, 0x30, 0x0, 0x7, 0xd1, 0x0, 0xab,
0x0, 0xc, 0x90, 0x0, 0x6, 0xd2, 0x0, 0x0,
0x3d, 0x40, 0x0, 0x2, 0xc2, 0x0, 0x0, 0x0,
/* U+003D "=" */
0x2d, 0xdd, 0xda, 0x0, 0x0, 0x0, 0x3d, 0xdd,
0xdb,
/* U+003E ">" */
0x21, 0x0, 0x5, 0xd2, 0x0, 0x3, 0xd4, 0x0,
0x2, 0xd6, 0x0, 0x6d, 0x20, 0x9b, 0x0, 0x88,
0x0, 0x0, 0x0, 0x0,
/* U+003F "?" */
0x3e, 0xc4, 0x0, 0x4, 0xe2, 0x0, 0xc, 0x50,
0x9d, 0xa0, 0x9, 0x50, 0x0, 0x52, 0x0, 0x5,
0x30, 0x0, 0xc7, 0x0,
/* U+0040 "@" */
0x0, 0x9b, 0xc5, 0x0, 0xb5, 0x0, 0xc1, 0x49,
0x5c, 0xc7, 0x69, 0x4d, 0x2d, 0x57, 0xd5, 0xa4,
0xa5, 0x7d, 0x59, 0x88, 0x94, 0xd1, 0xc7, 0xb9,
0xc, 0x10, 0x0, 0x0, 0x79, 0x0, 0x10, 0x0,
0x9c, 0xba, 0x0,
/* U+0041 "A" */
0x0, 0x8f, 0x20, 0x0, 0xd, 0xa8, 0x0, 0x3,
0xc3, 0xd0, 0x0, 0x87, 0xe, 0x20, 0xd, 0x20,
0x97, 0x2, 0xff, 0xff, 0xc0, 0x78, 0x0, 0xf,
0x1c, 0x40, 0x0, 0xb6,
/* U+0042 "B" */
0x1f, 0xee, 0xb1, 0x1f, 0x0, 0xa8, 0x1f, 0x0,
0x7a, 0x1f, 0x0, 0xc5, 0x1f, 0xdf, 0xd2, 0x1f,
0x0, 0x7d, 0x1f, 0x0, 0x6c, 0x1f, 0xdd, 0xb2,
/* U+0043 "C" */
0x0, 0xae, 0xea, 0xb, 0x90, 0x3, 0x3e, 0x0,
0x0, 0x5b, 0x0, 0x0, 0x6b, 0x0, 0x0, 0x4e,
0x0, 0x0, 0xd, 0x80, 0x2, 0x2, 0xbe, 0xe9,
/* U+0044 "D" */
0x5f, 0xed, 0x80, 0x5, 0xb0, 0xb, 0x90, 0x5b,
0x0, 0x2f, 0x5, 0xb0, 0x0, 0xf2, 0x5b, 0x0,
0xf, 0x15, 0xb0, 0x2, 0xe0, 0x5b, 0x1, 0xc8,
0x5, 0xfe, 0xd7, 0x0,
/* U+0045 "E" */
0xde, 0xee, 0x7d, 0x30, 0x0, 0xd3, 0x0, 0xd,
0x30, 0x0, 0xde, 0xee, 0x5d, 0x30, 0x0, 0xd3,
0x0, 0xd, 0xee, 0xe7,
/* U+0046 "F" */
0xce, 0xee, 0x7c, 0x40, 0x0, 0xc4, 0x0, 0xc,
0x40, 0x0, 0xce, 0xee, 0x4c, 0x40, 0x0, 0xc4,
0x0, 0xc, 0x40, 0x0,
/* U+0047 "G" */
0x1, 0xae, 0xfa, 0xd, 0x80, 0x4, 0x5c, 0x0,
0x0, 0x98, 0x0, 0x0, 0x88, 0x9, 0xdd, 0x6b,
0x0, 0x1f, 0xe, 0x60, 0x1f, 0x2, 0xbe, 0xea,
/* U+0048 "H" */
0x5b, 0x0, 0x1f, 0x5b, 0x0, 0x1f, 0x5b, 0x0,
0x1f, 0x5b, 0x0, 0x1f, 0x5f, 0xee, 0xef, 0x5b,
0x0, 0x1f, 0x5b, 0x0, 0x1f, 0x5b, 0x0, 0x1f,
/* U+0049 "I" */
0xde, 0xfe, 0x80, 0x3d, 0x0, 0x3, 0xd0, 0x0,
0x3d, 0x0, 0x3, 0xd0, 0x0, 0x3d, 0x0, 0x3,
0xd0, 0xe, 0xef, 0xe8,
/* U+004A "J" */
0xbe, 0xef, 0x20, 0x0, 0xe2, 0x0, 0xe, 0x20,
0x0, 0xe2, 0x0, 0xe, 0x20, 0x0, 0xe1, 0x30,
0x3e, 0xb, 0xed, 0x40,
/* U+004B "K" */
0x1f, 0x0, 0x99, 0x1, 0xf0, 0x5c, 0x0, 0x1f,
0x2d, 0x10, 0x1, 0xfd, 0x40, 0x0, 0x1f, 0xb8,
0x0, 0x1, 0xf1, 0xe4, 0x0, 0x1f, 0x4, 0xe1,
0x1, 0xf0, 0x8, 0xb0,
/* U+004C "L" */
0xa6, 0x0, 0xa, 0x60, 0x0, 0xa6, 0x0, 0xa,
0x60, 0x0, 0xa6, 0x0, 0xa, 0x60, 0x0, 0xa6,
0x0, 0xa, 0xee, 0xea,
/* U+004D "M" */
0x5f, 0x10, 0x8f, 0x6, 0xe6, 0xc, 0xe0, 0x79,
0xc3, 0x9e, 0x8, 0x6c, 0xa4, 0xd1, 0x85, 0x7e,
0xd, 0x29, 0x51, 0x40, 0xc3, 0xa4, 0x0, 0xc,
0x3b, 0x40, 0x0, 0xb4,
/* U+004E "N" */
0x4f, 0x40, 0x1e, 0x4e, 0xb0, 0x1e, 0x4a, 0xe2,
0x1e, 0x4a, 0x79, 0x1e, 0x4a, 0x1e, 0x2e, 0x4a,
0x9, 0x8e, 0x4a, 0x2, 0xee, 0x4a, 0x0, 0xae,
/* U+004F "O" */
0x4, 0xde, 0xb1, 0x2, 0xe3, 0x8, 0xb0, 0x7a,
0x0, 0xf, 0x1a, 0x70, 0x0, 0xd3, 0xa7, 0x0,
0xd, 0x38, 0x90, 0x0, 0xf1, 0x2f, 0x30, 0x9b,
0x0, 0x5e, 0xea, 0x10,
/* U+0050 "P" */
0x1f, 0xde, 0xb2, 0x1f, 0x0, 0x7b, 0x1f, 0x0,
0x2e, 0x1f, 0x0, 0x9a, 0x1f, 0xdd, 0x90, 0x1f,
0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0,
/* U+0051 "Q" */
0x4, 0xdf, 0xb1, 0x2, 0xe3, 0x8, 0xb0, 0x7a,
0x0, 0xf, 0x1a, 0x70, 0x0, 0xd3, 0xa7, 0x0,
0xd, 0x38, 0x90, 0x1, 0xf1, 0x2e, 0x41, 0x9a,
0x0, 0x5d, 0xf9, 0x0, 0x0, 0x2e, 0x11, 0x10,
0x0, 0x6d, 0xd4,
/* U+0052 "R" */
0xfe, 0xea, 0x0, 0xf0, 0xc, 0x60, 0xf0, 0x8,
0x80, 0xf0, 0x1d, 0x40, 0xfd, 0xf7, 0x0, 0xf0,
0x6c, 0x0, 0xf0, 0xc, 0x50, 0xf0, 0x4, 0xd0,
/* U+0053 "S" */
0x5, 0xde, 0xe4, 0x1e, 0x20, 0x0, 0x2f, 0x10,
0x0, 0x8, 0xf8, 0x10, 0x0, 0x29, 0xf4, 0x0,
0x0, 0x6c, 0x11, 0x0, 0x8a, 0x4e, 0xfe, 0xa1,
/* U+0054 "T" */
0x7e, 0xef, 0xee, 0x10, 0x3, 0xd0, 0x0, 0x0,
0x3d, 0x0, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x3d,
0x0, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x3d, 0x0,
0x0, 0x3, 0xd0, 0x0,
/* U+0055 "U" */
0x5b, 0x0, 0x1f, 0x5b, 0x0, 0x1f, 0x5b, 0x0,
0x1f, 0x5b, 0x0, 0x1f, 0x5b, 0x0, 0x1f, 0x5b,
0x0, 0x1e, 0x2e, 0x10, 0x7a, 0x6, 0xdd, 0xb1,
/* U+0056 "V" */
0xd5, 0x0, 0xb, 0x67, 0xa0, 0x0, 0xf1, 0x2f,
0x0, 0x4c, 0x0, 0xd4, 0x9, 0x60, 0x8, 0x90,
0xe1, 0x0, 0x3e, 0x3c, 0x0, 0x0, 0xeb, 0x70,
0x0, 0x9, 0xf2, 0x0,
/* U+0057 "W" */
0xb4, 0x0, 0x9, 0x4a, 0x50, 0x0, 0xa3, 0x96,
0x3, 0xb, 0x28, 0x75, 0xe0, 0xc1, 0x77, 0xad,
0x4d, 0x5, 0x9d, 0x59, 0xd0, 0x4d, 0x90, 0xed,
0x3, 0xf4, 0xb, 0xd0,
/* U+0058 "X" */
0x6d, 0x0, 0x3e, 0x0, 0xc6, 0xc, 0x50, 0x3,
0xe7, 0xb0, 0x0, 0x9, 0xf2, 0x0, 0x0, 0xbf,
0x50, 0x0, 0x5d, 0x5e, 0x0, 0xe, 0x40, 0xb8,
0x9, 0xb0, 0x2, 0xf2,
/* U+0059 "Y" */
0xb8, 0x0, 0xd, 0x53, 0xf1, 0x5, 0xc0, 0xa,
0x90, 0xd3, 0x0, 0x2f, 0x7b, 0x0, 0x0, 0x9f,
0x20, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x3d, 0x0,
0x0, 0x3, 0xd0, 0x0,
/* U+005A "Z" */
0x3f, 0xff, 0xfd, 0x0, 0x0, 0xc6, 0x0, 0x6,
0xc0, 0x0, 0x1e, 0x30, 0x0, 0xa8, 0x0, 0x4,
0xd0, 0x0, 0xd, 0x40, 0x0, 0x5f, 0xff, 0xfe,
/* U+005B "[" */
0xfd, 0xbf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf,
0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0xdb,
/* U+005C "\\" */
0xd, 0x20, 0x0, 0x6, 0x80, 0x0, 0x0, 0xe0,
0x0, 0x0, 0x96, 0x0, 0x0, 0x2c, 0x0, 0x0,
0xb, 0x30, 0x0, 0x5, 0xa0, 0x0, 0x0, 0xd1,
0x0, 0x0, 0x78, 0x0, 0x0, 0x16,
/* U+005D "]" */
0x4d, 0xe9, 0x0, 0x69, 0x0, 0x69, 0x0, 0x69,
0x0, 0x69, 0x0, 0x69, 0x0, 0x69, 0x0, 0x69,
0x0, 0x69, 0x4d, 0xe9,
/* U+005E "^" */
0x0, 0x6e, 0x0, 0x0, 0xc7, 0x80, 0x7, 0x60,
0xd1, 0x1d, 0x0, 0x5a,
/* U+005F "_" */
0xdd, 0xdd, 0xdd, 0x80,
/* U+0060 "`" */
0xd, 0x10, 0xf0, 0xd, 0x0,
/* U+0061 "a" */
0x8, 0xdd, 0xc1, 0x1, 0x0, 0x88, 0x5, 0xcc,
0xda, 0x1f, 0x20, 0x6a, 0x2e, 0x1, 0xca, 0x9,
0xec, 0x9a,
/* U+0062 "b" */
0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1e, 0x7d,
0xd2, 0x1f, 0x80, 0x6b, 0x1f, 0x0, 0x1e, 0x1f,
0x0, 0x2e, 0x1f, 0x0, 0x89, 0xc, 0xed, 0x90,
/* U+0063 "c" */
0x1, 0xae, 0xe6, 0xa, 0x90, 0x1, 0xf, 0x10,
0x0, 0xf, 0x10, 0x0, 0xc, 0x80, 0x1, 0x2,
0xbe, 0xe6,
/* U+0064 "d" */
0x0, 0x0, 0x6a, 0x0, 0x0, 0x6a, 0x3, 0xcd,
0xea, 0xe, 0x20, 0x6a, 0x4c, 0x0, 0x6a, 0x5b,
0x0, 0x6a, 0x2e, 0x1, 0xda, 0x8, 0xdb, 0x7a,
/* U+0065 "e" */
0x3, 0xcc, 0xb2, 0xd, 0x10, 0x5b, 0x3f, 0xcc,
0xcc, 0x4d, 0x0, 0x0, 0x1f, 0x40, 0x0, 0x4,
0xdd, 0xd7,
/* U+0066 "f" */
0x0, 0x1b, 0xdd, 0x20, 0x8, 0x90, 0x0, 0x0,
0xa6, 0x0, 0x7, 0xdf, 0xed, 0xd0, 0x0, 0xa6,
0x0, 0x0, 0xa, 0x60, 0x0, 0x0, 0xa6, 0x0,
0x0, 0xa, 0x60, 0x0,
/* U+0067 "g" */
0x5, 0xcd, 0xff, 0x10, 0xf1, 0xa, 0x60, 0xe,
0x20, 0xb5, 0x0, 0xcb, 0xc8, 0x0, 0x2d, 0x0,
0x0, 0x0, 0xee, 0xed, 0x80, 0x5c, 0x0, 0x3f,
0x2, 0xcd, 0xcc, 0x50,
/* U+0068 "h" */
0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x7d,
0xd2, 0x1f, 0x80, 0x89, 0x1f, 0x0, 0x5a, 0x1f,
0x0, 0x5a, 0x1f, 0x0, 0x5a, 0x1f, 0x0, 0x5a,
/* U+0069 "i" */
0x5, 0xe0, 0x0, 0x28, 0x0, 0xad, 0xf0, 0x0,
0x1f, 0x0, 0x1, 0xf0, 0x0, 0x1f, 0x0, 0x1,
0xf0, 0xd, 0xdf, 0xd9,
/* U+006A "j" */
0x0, 0x5, 0xe0, 0x0, 0x2, 0x80, 0xd, 0xdd,
0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0,
0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0,
0x0, 0x6, 0xb0, 0x2d, 0xdc, 0x20,
/* U+006B "k" */
0xf1, 0x0, 0x0, 0xf1, 0x0, 0x0, 0xf1, 0xb,
0x90, 0xf1, 0xa9, 0x0, 0xfb, 0xa0, 0x0, 0xf6,
0xd1, 0x0, 0xf1, 0x7d, 0x0, 0xf1, 0x9, 0xc0,
/* U+006C "l" */
0xad, 0xf0, 0x0, 0x1f, 0x0, 0x1, 0xf0, 0x0,
0x1f, 0x0, 0x1, 0xf0, 0x0, 0x1f, 0x0, 0x1,
0xf0, 0xd, 0xdf, 0xd9,
/* U+006D "m" */
0x79, 0xd7, 0xbb, 0x7, 0xc3, 0xf1, 0xe0, 0x77,
0x2c, 0xd, 0x17, 0x72, 0xc0, 0xd1, 0x77, 0x2c,
0xd, 0x17, 0x72, 0xc0, 0xd1,
/* U+006E "n" */
0x1e, 0x8c, 0xd2, 0x1f, 0x60, 0x79, 0x1f, 0x0,
0x5a, 0x1f, 0x0, 0x5a, 0x1f, 0x0, 0x5a, 0x1f,
0x0, 0x5a,
/* U+006F "o" */
0x4, 0xdd, 0xb2, 0x1, 0xe2, 0x7, 0xb0, 0x5a,
0x0, 0xf, 0x6, 0xa0, 0x0, 0xf0, 0x2e, 0x20,
0x7a, 0x0, 0x6d, 0xda, 0x10,
/* U+0070 "p" */
0x1e, 0x8c, 0xd2, 0x1f, 0x70, 0x5b, 0x1f, 0x0,
0x1e, 0x1f, 0x0, 0x2d, 0x1f, 0x0, 0x99, 0x1f,
0xed, 0xa0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0,
/* U+0071 "q" */
0x0, 0x0, 0x0, 0x3, 0xcd, 0xd9, 0xe, 0x20,
0x6a, 0x4b, 0x0, 0x6a, 0x5b, 0x0, 0x6a, 0x2e,
0x12, 0xea, 0x8, 0xec, 0x8a, 0x0, 0x0, 0x6a,
0x0, 0x0, 0x6a,
/* U+0072 "r" */
0xd6, 0xcd, 0x60, 0xdb, 0x2, 0xe0, 0xd3, 0x0,
0x40, 0xd3, 0x0, 0x0, 0xd3, 0x0, 0x0, 0xd3,
0x0, 0x0,
/* U+0073 "s" */
0x4c, 0xdd, 0x2c, 0x40, 0x0, 0x7d, 0x71, 0x0,
0x28, 0xe4, 0x10, 0x9, 0x8c, 0xee, 0xb1,
/* U+0074 "t" */
0x0, 0xb0, 0x0, 0x0, 0xf0, 0x0, 0x8d, 0xfd,
0xd9, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0,
0xf0, 0x0, 0x0, 0xe3, 0x0, 0x0, 0x5d, 0xd9,
/* U+0075 "u" */
0x1f, 0x0, 0x5a, 0x1f, 0x0, 0x5a, 0x1f, 0x0,
0x5a, 0xf, 0x0, 0x5a, 0xf, 0x10, 0xca, 0x7,
0xdc, 0x8a,
/* U+0076 "v" */
0x6b, 0x0, 0x2f, 0x1, 0xf1, 0x7, 0x90, 0xa,
0x70, 0xd3, 0x0, 0x4d, 0x3d, 0x0, 0x0, 0xeb,
0x60, 0x0, 0x8, 0xf1, 0x0,
/* U+0077 "w" */
0xb4, 0x0, 0xa, 0x59, 0x61, 0x50, 0xc2, 0x68,
0x6f, 0xe, 0x4, 0xab, 0xa5, 0xe0, 0x2d, 0xb3,
0xcb, 0x0, 0xf6, 0xd, 0x90,
/* U+0078 "x" */
0x2e, 0x20, 0x7c, 0x0, 0x6c, 0x2e, 0x10, 0x0,
0xae, 0x50, 0x0, 0xb, 0xf4, 0x0, 0x7, 0xc3,
0xe2, 0x3, 0xe2, 0x7, 0xc0,
/* U+0079 "y" */
0x6b, 0x0, 0x2e, 0x0, 0xf2, 0x8, 0x90, 0x9,
0x80, 0xd2, 0x0, 0x2e, 0x4c, 0x0, 0x0, 0xbd,
0x60, 0x0, 0x6, 0xe0, 0x0, 0x0, 0xc6, 0x0,
0x9, 0xe7, 0x0, 0x0,
/* U+007A "z" */
0xc, 0xdd, 0xf7, 0x0, 0x3, 0xe1, 0x0, 0x1d,
0x30, 0x0, 0xb7, 0x0, 0x7, 0xb0, 0x0, 0xf,
0xed, 0xd9,
/* U+007B "{" */
0x0, 0xb, 0xd3, 0x0, 0x5a, 0x0, 0x0, 0x68,
0x0, 0x0, 0x87, 0x0, 0xe, 0xd1, 0x0, 0x0,
0x97, 0x0, 0x0, 0x68, 0x0, 0x0, 0x69, 0x0,
0x0, 0x5b, 0x0, 0x0, 0xa, 0xd3,
/* U+007C "|" */
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x3c, 0x3c, 0x3c, 0x3c,
/* U+007D "}" */
0x8d, 0x60, 0x0, 0x1f, 0x0, 0x0, 0xf0, 0x0,
0xe, 0x20, 0x0, 0x5f, 0x80, 0xd, 0x20, 0x0,
0xf0, 0x0, 0xf, 0x0, 0x1, 0xe0, 0x8, 0xd5,
0x0,
/* U+007E "~" */
0x3d, 0xd7, 0x8, 0x15, 0x42, 0xae, 0xa0,
/* U+007F "" */
/* U+4E2D "中" */
0x0, 0x0, 0xb, 0x40, 0x0, 0x0, 0x0, 0x0,
0xb4, 0x0, 0x0, 0xa, 0xaa, 0xae, 0xca, 0xaa,
0x50, 0xf3, 0x33, 0xc6, 0x33, 0x88, 0xf, 0x0,
0xb, 0x40, 0x6, 0x80, 0xf0, 0x0, 0xb4, 0x0,
0x68, 0xf, 0xdd, 0xdf, 0xed, 0xde, 0x80, 0xa0,
0x0, 0xb5, 0x0, 0x45, 0x0, 0x0, 0xb, 0x40,
0x0, 0x0, 0x0, 0x0, 0xb4, 0x0, 0x0, 0x0,
0x0, 0xb, 0x40, 0x0, 0x0, 0x0, 0x0, 0xb4,
0x0, 0x0,
/* U+6587 "文" */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0xc, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8, 0x70,
0x0, 0x0, 0xce, 0xee, 0xee, 0xee, 0xee, 0xe5,
0x0, 0x86, 0x0, 0x0, 0xe1, 0x0, 0x0, 0x3b,
0x0, 0x3, 0xc0, 0x0, 0x0, 0xc, 0x20, 0x9,
0x60, 0x0, 0x0, 0x4, 0xc0, 0x3d, 0x0, 0x0,
0x0, 0x0, 0x9a, 0xe3, 0x0, 0x0, 0x0, 0x0,
0x6f, 0xd2, 0x0, 0x0, 0x0, 0x5c, 0xc3, 0x7e,
0xa4, 0x0, 0x8e, 0xc4, 0x0, 0x1, 0x8e, 0xf2,
0x22, 0x0, 0x0, 0x0, 0x0, 0x30
};
static const sgl_font_table_t sgl_ascii_consolas14_tab[] = {
{.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 = 106, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 0, .adv_w = 106, .box_w = 3, .box_h = 8, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 12, .adv_w = 106, .box_w = 5, .box_h = 3, .ofs_x = 1, .ofs_y = 5},
{.bitmap_index = 20, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 48, .adv_w = 106, .box_w = 6, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 84, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 112, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 140, .adv_w = 106, .box_w = 2, .box_h = 3, .ofs_x = 2, .ofs_y = 5},
{.bitmap_index = 143, .adv_w = 106, .box_w = 5, .box_h = 12, .ofs_x = 1, .ofs_y = -3},
{.bitmap_index = 173, .adv_w = 106, .box_w = 4, .box_h = 12, .ofs_x = 1, .ofs_y = -3},
{.bitmap_index = 197, .adv_w = 106, .box_w = 6, .box_h = 5, .ofs_x = 0, .ofs_y = 3},
{.bitmap_index = 212, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 233, .adv_w = 106, .box_w = 4, .box_h = 5, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 243, .adv_w = 106, .box_w = 5, .box_h = 1, .ofs_x = 1, .ofs_y = 3},
{.bitmap_index = 246, .adv_w = 106, .box_w = 3, .box_h = 2, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 249, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 277, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 305, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 329, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 353, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 377, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 405, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 425, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 449, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 473, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 497, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 521, .adv_w = 106, .box_w = 3, .box_h = 6, .ofs_x = 2, .ofs_y = 0},
{.bitmap_index = 530, .adv_w = 106, .box_w = 4, .box_h = 8, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 546, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = -1},
{.bitmap_index = 570, .adv_w = 106, .box_w = 6, .box_h = 3, .ofs_x = 0, .ofs_y = 2},
{.bitmap_index = 579, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = -1},
{.bitmap_index = 599, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 619, .adv_w = 106, .box_w = 7, .box_h = 10, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 654, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 682, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 706, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 730, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 758, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 778, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 798, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 822, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 846, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 866, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 886, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 914, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 934, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 962, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 986, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1014, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1038, .adv_w = 106, .box_w = 7, .box_h = 10, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1073, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 1097, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1121, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1149, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1173, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1201, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1229, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1257, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1285, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1309, .adv_w = 106, .box_w = 3, .box_h = 10, .ofs_x = 2, .ofs_y = -2},
{.bitmap_index = 1324, .adv_w = 106, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1354, .adv_w = 106, .box_w = 4, .box_h = 10, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 1374, .adv_w = 106, .box_w = 6, .box_h = 4, .ofs_x = 0, .ofs_y = 4},
{.bitmap_index = 1386, .adv_w = 106, .box_w = 7, .box_h = 1, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1390, .adv_w = 49, .box_w = 3, .box_h = 3, .ofs_x = 0, .ofs_y = 6},
{.bitmap_index = 1395, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1413, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1437, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1455, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1479, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1497, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1525, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1553, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1577, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 1597, .adv_w = 106, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1627, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 1651, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 1671, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1692, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1710, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1731, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1755, .adv_w = 106, .box_w = 6, .box_h = 9, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1782, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 1800, .adv_w = 106, .box_w = 5, .box_h = 6, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 1815, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1839, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1857, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1878, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1899, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1920, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1948, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 1966, .adv_w = 106, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 1996, .adv_w = 106, .box_w = 2, .box_h = 12, .ofs_x = 2, .ofs_y = -2},
{.bitmap_index = 2008, .adv_w = 106, .box_w = 5, .box_h = 10, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 2033, .adv_w = 106, .box_w = 7, .box_h = 2, .ofs_x = 0, .ofs_y = 2},
{.bitmap_index = 2040, .adv_w = 106, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 2040, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 2106, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2}
};
static const uint32_t unicode_list_1[] = {
0x0, 0x175a
};
static const sgl_font_unicode_t consolas14_unicode[] = {
{ .offset = 32, .len = 96, .list = NULL, .tab_offset = 1, },
{ .offset = 20013, .len = 2, .list = unicode_list_1, .tab_offset = 97, },
};
const sgl_font_t consolas14 = {
.bitmap = sgl_ascii_consolas14_bitmap,
.table = sgl_ascii_consolas14_tab,
.font_table_size = SGL_ARRAY_SIZE(sgl_ascii_consolas14_tab),
.font_height = 14,
.base_line = 3,
.bpp = 4,
.unicode = consolas14_unicode,
.unicode_num = 2,
};
#endif // !CONFIG_SGL_FONT_CONSOLAS14

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,392 @@
/* source/include/sgl_anim.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_ANIM_H__
#define __SGL_ANIM_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <sgl_cfgfix.h>
#include <stddef.h>
#include <sgl_list.h>
#include <sgl_types.h>
#include <sgl_mm.h>
#if (CONFIG_SGL_ANIMATION)
/* Forward declaration of sgl_pos sgl_anim structures */
struct sgl_pos;
struct sgl_anim;
/* Anim path callback */
typedef void (*sgl_anim_path_cb_t)(struct sgl_anim *anim, int32_t value);
typedef int32_t (*sgl_anim_path_algo_t)(uint32_t elaps, uint32_t duration, int32_t start, int32_t end);
/**
* @brief Animation object structure used to manage a single animation instance.
*
* This structure holds all the necessary state and configuration for an animation,
* including timing parameters, value interpolation, callbacks, and linkage in a list.
* All time values (act_delay, act_duration) are in milliseconds.
*
* @data: Pointer to user-defined private data associated with this animation.
* Not used internally by the animation engine; intended for application use.
*
* @next: Pointer to the next animation in a singly-linked list.
* Used internally by the animation scheduler to chain active animations.
*
* @act_delay: Delay time (in ms) before the animation starts after being added to the system.
* The animation will not progress until this delay has elapsed.
*
* @act_duration: Total duration (in ms) of the animation from start_value to end_value.
*
* @start_value: The initial value at the beginning of the animation (after delay).
*
* @end_value: The target value at the end of the animation.
*
* @path_cb: Optional custom callback function to compute intermediate animation values.
* If set, it overrides the built-in path algorithm (`path_algo`).
*
* @path_algo: Predefined interpolation algorithm (e.g., linear, ease-in, ease-out).
* Used only if `path_cb` is NULL.
*
* @finish_cb: Callback function invoked when the animation completes (including repeats).
* May be NULL if no cleanup or notification is needed.
*
* @repeat_cnt: Number of times the animation should repeat.
* - -1: play indefinitely, you can use SGL_ANIM_REPEAT_LOOP
* - 1: play once (no repeat), you can use SGL_ANIM_REPEAT_ONCE
* - n: repeat n times (total plays = n)
* @note Only 30 bits are allocated; max value is 0x3FFFFFFE.
*
* @finished: Flag indicating whether the animation has completed (including all repeats).
* Set to 1 when the animation ends naturally or is stopped.
*
* @auto_free: If set to 1, the animation object will be automatically freed after completion.
* Useful for fire-and-forget animations; ensure memory was allocated dynamically.
*/
typedef struct sgl_anim {
void *data;
struct sgl_anim *next;
uint32_t act_delay;
uint32_t act_duration;
int32_t start_value;
int32_t end_value;
sgl_anim_path_cb_t path_cb;
sgl_anim_path_algo_t path_algo;
void (*finish_cb)(struct sgl_anim *anim);
uint32_t repeat_cnt : 30;
uint32_t finished : 1;
uint32_t auto_free : 1;
} sgl_anim_t;
/**
* @brief animation context, it will be used to store status of animation
* @anim_list_head: animation list head
* @anim_list_tail: animation list tail
*/
typedef struct sgl_anim_ctx {
sgl_anim_t *anim_list_head;
sgl_anim_t *anim_list_tail;
} sgl_anim_ctx_t;
#define sgl_anim_for_each(anim, head) for ((anim) = (head)->anim_list_head; (anim) != NULL; (anim) = (anim)->next)
#define sgl_anim_for_each_safe(anim, n, head) for (anim = (head)->anim_list_head, n = (anim) ? (anim)->next : NULL; anim != NULL; anim = n, n = (anim) ? (anim)->next : NULL)
#define SGL_ANIM_REPEAT_LOOP (0x3FFFFFFF)
#define SGL_ANIM_REPEAT_ONCE (1)
/* Animation context it will be used internally */
extern sgl_anim_ctx_t sgl_anim_ctx;
/**
* @brief Animation static initialization
* @param anim - Animation object
* @return none
*/
void sgl_anim_init(sgl_anim_t *anim);
/**
* @brief dynamic alloc animation object with initialization
* @param none
* @return animation object
*/
sgl_anim_t* sgl_anim_create(void);
/**
* @brief start animation
* @param anim animation object
* @para repeat_cnt repeat count of animation
* @return none
*/
void sgl_anim_start(sgl_anim_t *anim, uint32_t repeat_cnt);
/**
* @brief stop animation
* @param anim animation object
* @return none
*/
void sgl_anim_stop(sgl_anim_t *anim);
/**
* @brief delete animation object
* @param anim animation object
* @return none
*/
void sgl_anim_delete(sgl_anim_t *anim);
/**
* @brief set animation private data
* @param anim animation object
* @param data pointer to private data
* @return none
*/
static inline void sgl_anim_set_data(sgl_anim_t *anim, void *data)
{
SGL_ASSERT(anim != NULL);
anim->data = data;
}
/**
* @brief set animation path callback function
* @param anim animation object
* @param path_cb path callback function
* @param path_algo path algo callback function
* @return none
*/
static inline void sgl_anim_set_path(sgl_anim_t *anim, sgl_anim_path_cb_t path_cb, sgl_anim_path_algo_t path_algo)
{
SGL_ASSERT(anim != NULL && path_cb != NULL && path_algo != NULL);
anim->path_cb = path_cb;
anim->path_algo = path_algo;
}
/**
* @brief set animation start value
* @param anim animation object
* @param value start value
* @return none
*/
static inline void sgl_anim_set_start_value(sgl_anim_t *anim, int32_t value)
{
SGL_ASSERT(anim != NULL);
anim->start_value = value;
}
/**
* @brief set animation end value
* @param anim animation object
* @param value end value
* @return none
*/
static inline void sgl_anim_set_end_value(sgl_anim_t *anim, int32_t value)
{
SGL_ASSERT(anim != NULL);
anim->end_value = value;
}
/**
* @brief set animation active delay time, ms
* @param anim animation object
* @param delay active delay time, ms
* @return none
*/
static inline void sgl_anim_set_act_delay(sgl_anim_t *anim, uint32_t delay_ms)
{
SGL_ASSERT(anim != NULL);
anim->act_delay = delay_ms;
}
/**
* @brief set animation active duration time, ms
* @param anim animation object
* @param duration active duration time, ms
* @return none
*/
static inline void sgl_anim_set_act_duration(sgl_anim_t *anim, uint32_t duration_ms)
{
SGL_ASSERT(anim != NULL);
anim->act_duration = duration_ms;
}
/**
* @brief set finish callback for animation
* @param anim animation object
* @param finish_cb finish callback
* @return none
*/
static inline void sgl_anim_set_finish_cb(sgl_anim_t *anim, void (*finish_cb)(sgl_anim_t *anim))
{
SGL_ASSERT(anim != NULL);
anim->finish_cb = finish_cb;
}
/**
* @brief check animation is finished or not
* @param anim animation object
* @return true or false
*/
static inline bool sgl_anim_is_finished(sgl_anim_t *anim)
{
SGL_ASSERT(anim != NULL);
return (bool)anim->finished;
}
/**
* @brief set auto free flag for animation
* @param anim animation
* @return none
*/
static inline void sgl_anim_set_auto_free(sgl_anim_t *anim)
{
SGL_ASSERT(anim != NULL);
anim->auto_free = 1;
}
/**
* @brief animation task, it will foreach all animation
* @param none
* @return none
* @note this function should be called in sgl_task()
*/
void sgl_anim_task(void);
/**
* Linear animation path calculation function
*
* Calculates the current interpolated value based on elapsed time and total duration
* using linear interpolation.
*
* @param elaps Elapsed time in milliseconds
* @param duration Total animation duration in milliseconds
* @param start Start value
* @param end End value
*
* @return The interpolated value for the current time
*
* @note Returns 'end' if elaps >= duration (animation finished)
* Returns 'start' if elaps == 0 (animation just started)
* Uses 32-bit integer arithmetic to avoid floating-point operations
* for better performance on embedded systems
*/
int32_t sgl_anim_path_linear(uint32_t elaps, uint32_t duration, int32_t start, int32_t end);
#define SGL_ANIM_PATH_LINEAR sgl_anim_path_linear
/**
* sgl_anim_path_ease_in_out - Cubic ease-in-out animation path
*
* This function creates a smooth animation curve that starts slow,
* accelerates in the middle, and decelerates at the end.
*
* @param elaps Elapsed time (ms)
* @param duration Total animation duration (ms)
* @param start Start value
* @param end End value
* @return Interpolated value at current time
*/
int32_t sgl_anim_path_ease_in_out(uint32_t elaps, uint32_t duration, int32_t start, int32_t end);
#define SGL_ANIM_PATH_EASE_IN_OUT sgl_anim_path_ease_in_out
/**
* sgl_anim_path_ease_in - Cubic ease-in animation path
*
* This function creates a smooth animation curve that starts slow,
* accelerates in the after
*
* @param elaps Elapsed time (ms)
* @param duration Total animation duration (ms)
* @param start Start value
* @param end End value
* @return Interpolated value at current time
*/
int32_t sgl_anim_path_ease_out(uint32_t elaps, uint32_t duration, int32_t start, int32_t end);
#define SGL_ANIM_PATH_EASE_OUT sgl_anim_path_ease_out
/**
* sgl_anim_path_ease_in - Cubic ease-in animation path
*
* This function creates a smooth animation curve that starts accelerates,
* accelerates in the after
*
* @param elaps Elapsed time (ms)
* @param duration Total animation duration (ms)
* @param start Start value
* @param end End value
* @return Interpolated value at current time
*/
int32_t sgl_anim_path_ease_in(uint32_t elaps, uint32_t duration, int32_t start, int32_t end);
#define SGL_ANIM_PATH_EASE_IN sgl_anim_path_ease_in
/**
* sgl_anim_path_overshoot - Overshoot animation path
*
* This function creates an animation curve that overshoots the target end value
* slightly before settling back to it, creating a natural "bounce" or "spring-like"
* effect for a more dynamic and realistic animation.
*
* @param elaps Elapsed time (ms) since the animation started
* @param duration Total animation duration (ms)
* @param start Initial value of the animated property at the start of the animation
* @param end Target end value of the animated property
* @return Interpolated value of the animated property at the current elapsed time
*/
int32_t sgl_anim_path_overshoot(uint32_t elaps, uint32_t duration, int32_t start, int32_t end);
#define SGL_ANIM_PATH_OVERSHOOT sgl_anim_path_overshoot
#endif // ! CONFIG_SGL_ANIMATION
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif // ! __SGL_ANIM_H__

View File

@ -0,0 +1,230 @@
/* source/include/sgl_cfgfix.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_CFGFIX_H__
#define __SGL_CFGFIX_H__
#include <sgl_config.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief sgl config fix file, it will fix the macro if not defined
* @note please add the macro in this file if you want to add new macro into source code
*
* @description:
*
* CONFIG_SGL_FBDEV_PIXEL_DEPTH:
* The pixel depth of framebuffer device, it will be used to define the color type
*
* CONFIG_SGL_FBDEV_ROTATION:
* The rotation of framebuffer device, default: 0
*
* CONFIG_SGL_FBDEV_RUNTIME_ROTATION:
* If you want to use runtime rotation, please define this macro to 1
*
* CONFIG_SGL_USE_FBDEV_VRAM:
* If you want to use full framebuffer, please define this macro to 1
*
* CONFIG_SGL_SYSTICK_MS:
* The macro should be defined to the system tick ms, default: 10
*
* CONFIG_SGL_COLOR16_SWAP:
* Its for 16 bit color, the color will be swapped
*
* CONFIG_SGL_EVENT_QUEUE_SIZE:
* the size of event queue, default: 32
*
* CONFIG_SGL_EVENT_CLICK_INTERVAL:
* The click interval, default: 10
*
* CONFIG_SGL_OBJ_SLOT_DYNAMIC
* If the object slot is dynamic, the object slot size will be dynamic allocated, otherwise, the object
* slot size will be static allocated that you should define CONFIG_SGL_OBJ_NUM_MAX macro
*
* CONFIG_SGL_OBJ_NUM_MAX:
* If CONFIG_SGL_OBJ_SLOT_DYNAMIC is 0 or not defined, you should define CONFIG_SGL_OBJ_NUM_MAX macro
*
* CONFIG_SGL_PIXMAP_BILINEAR_INTERP:
* If you want to use pixmap bilinear interpolation, please define this macro to 1
*
* CONFIG_SGL_ANIMATION:
* If you want to use animation, please define this macro to 1
*
* CONFIG_SGL_DEBUG:
* If you want to use debug, please define this macro to 1
*
* CONFIG_SGL_USE_OBJ_ID:
* If you want to use obj id, please define this macro to 1, at mostly, the CONFIG_SGL_USE_OBJ_ID should be 0
*
* CONFIG_SGL_HEAP_ALGO:
* The heap algorithm, default: lwmem
*
* CONFIG_SGL_HEAP_MEMORY_SIZE:
* The heap memory size, default: 10240
*
* CONFIG_SGL_FONT_COMPRESSED:
* If you want to use font compressed, please define this macro to 1
*
* CONFIG_SGL_FONT_SMALL_TABLE:
* If you want to use font small table, please define this macro to 1
*
* CONFIG_SGL_LABEL_ROTATION:
* If you want to use label rotation, please define this macro to 1
*
* CONFIG_SGL_FONT_SONG23:
* If you want to use font song23, please define this macro to 1
*
* CONFIG_SGL_FONT_CONSOLAS23:
* If you want to use font consolas23, please define this macro to 1
*
*/
#ifndef CONFIG_SGL_FBDEV_PIXEL_DEPTH
#define CONFIG_SGL_FBDEV_PIXEL_DEPTH (16)
#endif
#ifndef CONFIG_SGL_FBDEV_ROTATION
#define CONFIG_SGL_FBDEV_ROTATION (0)
#endif
#ifndef CONFIG_SGL_FBDEV_RUNTIME_ROTATION
#define CONFIG_SGL_FBDEV_RUNTIME_ROTATION (0)
#endif
#ifndef CONFIG_SGL_USE_FBDEV_VRAM
#define CONFIG_SGL_USE_FBDEV_VRAM (0)
#endif
#ifndef CONFIG_SGL_SYSTICK_MS
#define CONFIG_SGL_SYSTICK_MS (10)
#endif
#ifndef CONFIG_SGL_COLOR16_SWAP
#define CONFIG_SGL_COLOR16_SWAP (0)
#endif
#ifndef CONFIG_SGL_EVENT_QUEUE_SIZE
#define CONFIG_SGL_EVENT_QUEUE_SIZE (16)
#endif
#ifndef CONFIG_SGL_EVENT_CLICK_INTERVAL
#define CONFIG_SGL_EVENT_CLICK_INTERVAL (10)
#endif
#ifndef CONFIG_SGL_DIRTY_AREA_NUM_MAX
#define CONFIG_SGL_DIRTY_AREA_NUM_MAX (16)
#endif
#ifndef CONFIG_SGL_PIXMAP_BILINEAR_INTERP
#define CONFIG_SGL_PIXMAP_BILINEAR_INTERP (0)
#endif
#ifndef CONFIG_SGL_ANIMATION
#define CONFIG_SGL_ANIMATION (0)
#endif
#ifndef CONFIG_SGL_DEBUG
# define CONFIG_SGL_DEBUG (0)
#elif (CONFIG_SGL_DEBUG == 1)
# ifndef CONFIG_SGL_LOG_COLOR
# define CONFIG_SGL_LOG_COLOR (0)
# endif
# ifndef CONFIG_SGL_LOG_LEVEL
# define CONFIG_SGL_LOG_LEVEL (1)
# endif
#endif
#ifndef CONFIG_SGL_OBJ_USE_NAME
#define CONFIG_SGL_OBJ_USE_NAME (0)
#endif
#ifndef CONFIG_SGL_HEAP_ALGO
#define CONFIG_SGL_HEAP_ALGO (lwmem)
#endif
#ifndef CONFIG_SGL_HEAP_MEMORY_SIZE
# define CONFIG_SGL_HEAP_MEMORY_SIZE (10240)
# ifndef CONFIG_SGL_FL_INDEX_MAX
# define CONFIG_SGL_FL_INDEX_MAX (20)
# endif
#endif
#ifndef CONFIG_SGL_FONT_COMPRESSED
#define CONFIG_SGL_FONT_COMPRESSED (0)
#endif
#ifndef CONFIG_SGL_FONT_SMALL_TABLE
#define CONFIG_SGL_FONT_SMALL_TABLE (0)
#endif
#ifndef CONFIG_SGL_LABEL_ROTATION
#define CONFIG_SGL_LABEL_ROTATION (0)
#endif
#ifndef CONFIG_SGL_FONT_SONG23
#define CONFIG_SGL_FONT_SONG23 (0)
#endif
#ifndef CONFIG_SGL_FONT_CONSOLAS14
#define CONFIG_SGL_FONT_CONSOLAS14 (0)
#endif
#ifndef CONFIG_SGL_FONT_CONSOLAS23
#define CONFIG_SGL_FONT_CONSOLAS23 (0)
#endif
#ifndef CONFIG_SGL_FONT_CONSOLAS24
#define CONFIG_SGL_FONT_CONSOLAS24 (0)
#endif
#ifndef CONFIG_SGL_FONT_CONSOLAS32
#define CONFIG_SGL_FONT_CONSOLAS32 (0)
#endif
#if !(CONFIG_SGL_THEME_DARK || CONFIG_SGL_THEME_LIGHT)
# ifndef CONFIG_SGL_THEME_DEFAULT
# define CONFIG_SGL_THEME_DEFAULT (1)
# endif
#endif
#ifndef CONFIG_SGL_BOOT_LOGO
#define CONFIG_SGL_BOOT_LOGO (1)
#endif
#ifndef CONFIG_SGL_BOOT_ANIMATION
# define CONFIG_SGL_BOOT_ANIMATION (0)
#elif (CONFIG_SGL_ANIMATION == 0)
# undef CONFIG_SGL_BOOT_ANIMATION
# define CONFIG_SGL_BOOT_ANIMATION (0)
#endif
#ifdef __cplusplus
}
#endif
#endif // !__SGL_CFGFIX_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,513 @@
/* source/include/sgl_draw.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_DRAW_H__
#define __SGL_DRAW_H__
#include <sgl_core.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SGL_ARC_MODE_NORMAL (0)
#define SGL_ARC_MODE_RING (1)
#define SGL_ARC_MODE_NORMAL_SMOOTH (2)
#define SGL_ARC_MODE_RING_SMOOTH (3)
/**
* @brief rect description
* @color: color of rect
* @alpha: alpha of rect
* @border: border of rect
* @border_color: border color of rect
* @pixmap: pixmap of rect
*/
typedef struct sgl_draw_rect {
sgl_color_t color;
int16_t radius;
uint8_t alpha;
uint8_t border;
sgl_color_t border_color;
const sgl_pixmap_t *pixmap;
} sgl_draw_rect_t;
/**
* @brief line draw description
* @x1: x1 coordinate
* @y1: y1 coordinate
* @x2: x2 coordinate
* @y2: y2 coordinate
* @color: color
* @alpha: alpha
* @width: width of line
*/
typedef struct sgl_draw_line {
int16_t x1;
int16_t y1;
int16_t x2;
int16_t y2;
sgl_color_t color;
uint8_t alpha;
uint8_t width;
} sgl_draw_line_t;
/**
* @brief rectangle description
* @cx: center x of rectangle
* @cy: center y of rectangle
* @color: color of rectangle
* @radius: radius of rectangle
* @alpha: alpha of rectangle
* @border: border of rectangle
* @border_color: border color of rectangle
* @pixmap: pixmap of rectangle
*/
typedef struct sgl_draw_circle {
int16_t cx;
int16_t cy;
sgl_color_t color;
int16_t radius;
uint8_t alpha;
uint8_t border;
sgl_color_t border_color;
const sgl_pixmap_t *pixmap;
} sgl_draw_circle_t;
/**
* @brief arc description
* @cx: center x
* @cy: center y
* @radius_in: inner radius of arc
* @radius_out: outer radius of arc
* @start_angle: start angle of arc
* @end_angle: end angle of arc
* @color: color of arc
* @alpha: alpha of arc
* @mode: mode of arc
* @bg_color: background color of arc
*/
typedef struct sgl_draw_arc {
int16_t cx;
int16_t cy;
int16_t radius_in;
int16_t radius_out;
sgl_color_t color;
uint8_t alpha;
uint32_t start_angle: 9;
uint32_t end_angle: 9;
uint32_t mode: 2;
sgl_color_t bg_color;
} sgl_draw_arc_t;
/**
* @brief icon description
* @icon: icon pixmap
* @color: icon color
* @alpha: alpha of icon
*/
typedef struct sgl_draw_icon {
const sgl_icon_pixmap_t *icon;
sgl_color_t color;
uint8_t alpha;
uint8_t align;
} sgl_draw_icon_t;
/**
* @brief clip area width of surface
* @note if you want to check the area is overlap with surface, you can use this macro
* it will direct return if the area is not overlap with surface, otherwise, continue
*/
#if (CONFIG_SGL_USE_FBDEV_VRAM)
#define sgl_surf_clip_area_return(surf, rect, clip) do {SGL_UNUSED(rect);} while(0)
#else
#define sgl_surf_clip_area_return(surf, rect, clip) if (!sgl_surf_clip(surf, rect, clip)) return
#endif
/**
* @brief set pixel on surface
* @param surf: pointer of surface
* @param x: x coordinate
* @param y: y coordinate
* @param color: color of pixel
* @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface.
*/
static inline void sgl_surf_set_pixel(sgl_surf_t *surf, int16_t x, int16_t y, sgl_color_t color)
{
surf->buffer[y * surf->w + x] = color;
}
/**
* @brief get start buffer address that to set pixel on surface
* @param surf: pointer of surface
* @param x: x coordinate
* @param y: y coordinate
* @return pointer of start buffer address
* @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface.
*/
static inline sgl_color_t* sgl_surf_get_buf(sgl_surf_t *surf, int16_t x, int16_t y)
{
return &surf->buffer[y * surf->w + x];
}
/**
* @brief get pixel on surface
* @param surf: pointer of surface
* @param x: x coordinate
* @param y: y coordinate
* @return color of pixel
* @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface.
*/
static inline sgl_color_t sgl_surf_get_pixel(sgl_surf_t *surf, int16_t x, int16_t y)
{
return surf->buffer[y * surf->w + x];
}
/**
* @brief draw a horizontal line on surface
* @param surf: pointer of surface
* @param y: y coordinate
* @param x1: x1 coordinate
* @param x2: x2 coordinate
* @param color: color of line
* @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface.
*/
static inline void sgl_surf_hline(sgl_surf_t *surf, int16_t y, int16_t x1, int16_t x2, sgl_color_t color)
{
sgl_color_t *dst = surf->buffer + y * surf->w + x1;
for (int16_t i = x1; i <= x2; i++) {
*dst = color;
dst++;
}
}
/**
* @brief draw a vertical line on surface
* @param surf: pointer of surface
* @param x: x coordinate
* @param y1: y1 coordinate
* @param y2: y2 coordinate
* @param color: color of line
* @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface.
*/
static inline void sgl_surf_vline(sgl_surf_t *surf, int16_t x, int16_t y1, int16_t y2, sgl_color_t color)
{
sgl_color_t *dst = surf->buffer + y1 * surf->w + x;
for (int16_t i = y1; i <= y2; i++) {
*dst = color;
dst += surf->w;
}
}
/**
* @brief fill a round rectangle with alpha
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param radius radius of round
* @param color color of rectangle
* @param alpha alpha of rectangle
* @return none
*/
void sgl_draw_fill_rect(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, sgl_color_t color, uint8_t alpha);
/**
* @brief fill a round rectangle with alpha and border
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param radius radius of round
* @param color color of rectangle
* @param border_color color of border
* @param border_width width of border
* @param alpha alpha of rectangle
* @return none
*/
void sgl_draw_fill_rect_with_border(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, sgl_color_t color, sgl_color_t border_color, uint8_t border_width, uint8_t alpha);
/**
* @brief fill a round rectangle pixmap with alpha
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param radius radius of round
* @param pixmap pixmap of rectangle
* @param alpha alpha of rectangle
* @return none
*/
void sgl_draw_fill_rect_pixmap(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha);
/**
* @brief fill a round rectangle with alpha
* @param surf point to surface
* @param area area of rectangle that you want to draw
* @param rect point to rectangle that you want to draw
* @param desc rectangle description
* @return none
*/
void sgl_draw_rect(sgl_surf_t *surf, sgl_area_t *area, sgl_rect_t *rect, sgl_draw_rect_t *desc);
/**
* @brief Draw a circle
* @param surf Surface
* @param area Area of the circle
* @param cx X coordinate of the center
* @param cy Y coordinate of the center
* @param radius Radius of the circle
* @param color Color of the circle
* @param alpha Alpha of the circle
* @return none
*/
void sgl_draw_fill_circle(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, sgl_color_t color, uint8_t alpha);
/**
* @brief Draw a circle with pixmap and alpha
* @param surf Surface
* @param area Area of the circle
* @param cx X coordinate of the center
* @param cy Y coordinate of the center
* @param radius Radius of the circle
* @param pixmap Pixmap of image
* @param alpha Alpha of the circle
* @return none
*/
void sgl_draw_fill_circle_pixmap(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha);
/**
* @brief Draw a circle with alpha and border
* @param surf Surface
* @param area Area of the circle
* @param cx X coordinate of the center
* @param cy Y coordinate of the center
* @param radius Radius of the circle
* @param color Color of the circle
* @param border_color Color of the border
* @param border_width Width of the border
* @param alpha Alpha of the circle
* @return none
*/
void sgl_draw_fill_circle_with_border(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, sgl_color_t color, sgl_color_t border_color, int16_t border_width, uint8_t alpha);
/**
* @brief draw task, the task contains the draw information and canvas
* @param surf surface pointer
* @param area the area of the task
* @param desc the draw information
* @return none
*/
void sgl_draw_circle(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_circle_t *desc);
/**
* @brief draw icon with alpha
* @param surf surface
* @param area area of icon
* @param coords coords of icon
* @param icon icon pixmap
* @param alpha alpha of icon
*/
void sgl_draw_icon( sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, sgl_color_t color, uint8_t alpha, const sgl_icon_pixmap_t *icon);
/**
* @brief Draw a character on the surface with alpha blending
* @param surf Pointer to the surface where the character will be drawn
* @param area Pointer to the area where the character will be drawn
* @param x X coordinate where the character will be drawn
* @param y Y coordinate where the character will be drawn
* @param ch_index Index of the character in the font table
* @param color Foreground color of the character
* @param alpha Alpha value for blending
* @param font Pointer to the font structure containing character data
* @return none
* @note this function is only support bpp:4
*/
void sgl_draw_character( sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, uint32_t ch_index, sgl_color_t color, uint8_t alpha, const sgl_font_t *font);
/**
* @brief Draw a string on the surface with alpha blending
* @param surf Pointer to the surface where the string will be drawn
* @param area Pointer to the area where the string will be drawn
* @param x X coordinate of the top-left corner of the string
* @param y Y coordinate of the top-left corner of the string
* @param str Pointer to the string to be drawn
* @param color Foreground color of the string
* @param alpha Alpha value for blending
* @param font Pointer to the font structure containing character data
* @return none
*/
void sgl_draw_string(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, const char *str, sgl_color_t color, uint8_t alpha, const sgl_font_t *font);
/**
* @brief Draw a string on the surface with alpha blending and multiple lines
* @param surf Pointer to the surface where the string will be drawn
* @param area Pointer to the area where the string will be drawn
* @param x X coordinate of the top-left corner of the string
* @param y Y coordinate of the top-left corner of the string
* @param str Pointer to the string to be drawn
* @param color Foreground color of the string
* @param alpha Alpha value for blending
* @param font Pointer to the font structure containing character data
* @param line_margin Margin between lines
* @return none
*/
void sgl_draw_string_mult_line(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, const char *str, sgl_color_t color, uint8_t alpha, const sgl_font_t *font, uint8_t line_margin);
/**
* @brief draw a ring on surface with alpha
* @param surf: pointer of surface
* @param area: pointer of area
* @param cx: ring center x
* @param cy: ring center y
* @param radius_in: ring inner radius
* @param radius_out: ring outer radius
* @param color: ring color
* @param alpha: ring alpha
* @return none
*/
void sgl_draw_fill_ring(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius_in, int16_t radius_out, sgl_color_t color, uint8_t alpha);
/**
* @brief draw a horizontal line with alpha
* @param surf surface
* @param area area that contains the line
* @param y line y position
* @param x1 line start x position
* @param x2 line end x position
* @param color line color
* @param alpha alpha of color
* @return none
*/
void sgl_draw_fill_hline(sgl_surf_t *surf, sgl_area_t *area, int16_t y, int16_t x1, int16_t x2, uint8_t width, sgl_color_t color, uint8_t alpha);
/**
* @brief draw a vertical line with alpha
* @param surf surface
* @param area area that contains the line
* @param x x coordinate
* @param y1 y1 coordinate
* @param y2 y2 coordinate
* @param color line color
* @param alpha alpha of color
* @return none
*/
void sgl_draw_fill_vline(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y1, int16_t y2, uint8_t width, sgl_color_t color, uint8_t alpha);
/**
* @brief draw a slanted line with alpha
* @param surf surface
* @param area area that contains the line
* @param x1 line start x position
* @param y1 line start y position
* @param x2 line end x position
* @param y2 line end y position
* @param thickness line width
* @param color line color
* @param alpha alpha of color
* @return none
* @note This algorithm is SDF algorithm
*/
void draw_line_fill_slanted(sgl_surf_t *surf, sgl_area_t *area, int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t thickness, sgl_color_t color, uint8_t alpha);
/**
* @brief draw a line
* @param surf surface
* @param area area that contains the line
* @param desc line description
* @return none
*/
void sgl_draw_line(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_line_t *desc);
/**
* @brief draw an arc with alpha
* @param surf pointer to surface
* @param area pointer to area
* @param desc pointer to arc description
* @return none
*/
void sgl_draw_fill_arc(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_arc_t *desc);
/**
* @brief calculate a point color by bilinear interpolate
* @param buffer point to image pixmap start buffer
* @param w width of buffer
* @param h height of buffer
* @param fx x coordinate of point
* @param fy y coordinate of point
* @return point color
*/
sgl_color_t sgl_draw_biln_color(const sgl_color_t *buffer, int16_t w, int16_t h, int32_t fx, int32_t fy);
/**
* @brief transform a surface
* @param dst destination surface
* @param src source surface
* @param area area of surface
* @param x x coordinate of surface
* @param y y coordinate of surface
* @param rotation rotation angle
* @return none
* @note This function has implemented angle normalization to the range of 0 to 360 degrees.
*/
void sgl_draw_xform_surf(sgl_surf_t *dst, sgl_surf_t *src, sgl_area_t *area, int16_t x, int16_t y, int16_t rotation);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif

View File

@ -0,0 +1,170 @@
/* source/include/sgl_errno.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_ERRNO_H__
#define __SGL_ERRNO_H__
#define OK 0 /* No error */
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
/* for robust mutexes */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
#define ERFKILL 132 /* Operation not possible due to RF-kill */
#define EHWPOISON 133 /* Memory page has hardware error */
#endif // !__SGL_ERRNO_H__

View File

@ -0,0 +1,220 @@
/* source/include/sgl_event.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_EVENT_H__
#define __SGL_EVENT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <sgl_cfgfix.h>
#include <stddef.h>
#include <sgl_list.h>
#include <sgl_types.h>
/* Forward declaration of sgl_obj and sgl_page*/
struct sgl_obj;
struct sgl_page;
/**
* @brief Event type enumeration
* @note The event type is used to describe the type of event, such as click,
* long press, etc. The event type is used to distinguish different events,
* and the event type is used to trigger different callbacks
*/
#define SGL_EVENT_NULL (0)
#define SGL_EVENT_NORMAL (1)
#define SGL_EVENT_PRESSED (2)
#define SGL_EVENT_RELEASED (3)
#define SGL_EVENT_CLICKED (4)
#define SGL_EVENT_LONG_CLICKED (5)
#define SGL_EVENT_MOTION (6)
#define SGL_EVENT_MOVE_UP (7)
#define SGL_EVENT_MOVE_DOWN (8)
#define SGL_EVENT_MOVE_LEFT (9)
#define SGL_EVENT_MOVE_RIGHT (10)
#define SGL_EVENT_LONG_PRESSED (11)
#define SGL_EVENT_OPTION_WALK (12)
#define SGL_EVENT_OPTION_TAP (13)
#define SGL_EVENT_DRAW_INIT (14)
#define SGL_EVENT_DRAW_MAIN (15)
#define SGL_EVENT_FOCUSED (16)
#define SGL_EVENT_UNFOCUSED (17)
#define SGL_EVENT_DESTROYED (18)
#define sgl_event_type_t uint8_t
#define SGL_EVENT_CLICK_INTERVAL (CONFIG_SGL_EVENT_CLICK_INTERVAL)
/**
* @brief Event location structure, Used to represent the coordinates of an event,
* such as the click position of the mouse, the click position of the touch screen,
* and so on
*
* @x: x coordinate
* @y: y coordinate
*/
typedef struct sgl_event_pos {
int16_t x;
int16_t y;
} sgl_event_pos_t;
typedef struct sgl_event {
struct sgl_obj *obj;
void *param;
sgl_event_pos_t pos;
uint16_t type;
uint16_t distance;
} sgl_event_t;
/**
* @brief Initialize the event queue
* @param none
* @return 0 on success, -1 on failure
* @note !!!!!! the SGL_EVENT_QUEUE_SIZE must be power of 2 !!!!!!
* You must check the return value of this function.
*/
int sgl_event_queue_init(void);
/**
* @brief Push an event into the event queue
* @param event The event to be pushed
* @return 0 on success, -1 on failure
*/
void sgl_event_queue_push(sgl_event_t event);
/**
* @brief Handle the position event
* @param pos The position to be handled
* @param type The type of the event
* @return none
*/
void sgl_event_send_pos(sgl_event_pos_t pos, sgl_event_type_t type);
/**
* @brief Send an event to the specified object
* @param event The event to be sent
* @return none
*/
static inline void sgl_event_send(sgl_event_t event)
{
sgl_event_queue_push(event);
}
/**
* @brief Send an event to the specified object
* @param obj The object to be sent
* @param type The type of the event
* @return none
* @note This function is used to send an event to the specified object, for example,
* if you want to send an event to the button, you can call:
* ---- press button case : sgl_event_send_obj(button, SGL_EVENT_PRESSED);
* ---- release button case: sgl_event_send_obj(button, SGL_EVENT_RELEASED);
*
* @tip: You can also send you own event to the specified object, for example,
* The MY_EVENT_TYPE is defined by you, and you can use it in your own event handler, for example:
* ...
* sgl_event_send_obj(button, MY_EVENT_TYPE);
* ...
* void my_event_handler(sgl_event_t *event)
* {
* if (event->type == MY_EVENT_TYPE) {
* // do something
* }
* }
*/
static inline void sgl_event_send_obj(struct sgl_obj *obj, sgl_event_type_t type)
{
sgl_event_t event = {0};
event.obj = obj;
event.type = type;
sgl_event_send(event);
}
/**
* @brief Send a motion event to the specified object
* @param pos The position of the motion event
* @param type The type of the motion event
* @param distance The distance of the motion event
* @return none
*/
static inline void sgl_event_send_motion(sgl_event_pos_t pos, sgl_event_type_t type, uint16_t distance)
{
sgl_event_t event = {0};
event.pos = pos;
event.type = type;
event.distance = distance;
sgl_event_send(event);
}
/**
* @brief All event task in SGL, this function will traverse all elements in the event queue,
* respond to each element with an event, so that all events will trigger and point to the
* corresponding callback function
* @param none
* @return none
*/
void sgl_event_task(void);
/**
* @brief Touch event read, this function will be called by user
* @param x: touch x position
* @param y: touch y position
* @param flag: touch flag, it means touch event down or up:
* true : touch down
* false: touch up
* @return none
* @note: for example, you can call it in 30ms tick handler function
* void example_30ms_tick_handler(void)
* {
* int pos_x, pos_y;
* bool button_status;
*
* bsp_touch_read_pos(&pos_x, &pos_y);
* button_status = bsp_touch_read_status();
*
* sgl_event_pos_input(pos_x, pos_y, button_status);
* }
*/
void sgl_event_pos_input(int16_t x, int16_t y, bool flag);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif //!__SGL_EVENT_H__

View File

@ -0,0 +1,66 @@
/* source/include/sgl_font.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_FONT_H__
#define __SGL_FONT_H__
#include <sgl_cfgfix.h>
#include <stddef.h>
#include <sgl_list.h>
#include <sgl_types.h>
#include <sgl_core.h>
/* declare all font */
#if CONFIG_SGL_FONT_SONG23
extern const sgl_font_t song23;
#endif
#if CONFIG_SGL_FONT_CONSOLAS14
extern const sgl_font_t consolas14;
#endif
#if CONFIG_SGL_FONT_CONSOLAS23
extern const sgl_font_t consolas23;
#endif
#if CONFIG_SGL_FONT_CONSOLAS24
extern const sgl_font_t consolas24;
#endif
#if CONFIG_SGL_FONT_CONSOLAS32
extern const sgl_font_t consolas32;
#endif
#if CONFIG_SGL_FONT_KAI33
extern const sgl_font_t kai33;
#endif
#if CONFIG_SGL_FONT_CONSOLAS24_COMPRESS
extern const sgl_font_t consolas24_compress;
#endif
#endif // !__SGL_FONT_H__

View File

@ -0,0 +1,307 @@
/* source/include/sgl_list.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_LIST_H__
#define __SGL_LIST_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
/**
* @prev: previous node of the list.
* @next: next node of the list.
*/
typedef struct sgl_list_node {
struct sgl_list_node *prev;
struct sgl_list_node *next;
}sgl_list_node_t;
#define SGL_LIST_HEAD(name) \
sgl_list_node_t name = {.prev = &(name), .next = &(name)}
/**
* @brief foreach the list.
*
* @pos: the &struct list_head to use as a loop cursor.
* @list_head: the head for your list.
*
* @return none
*/
#define sgl_list_for_each(pos, list_head) \
for (pos = (list_head)->next; pos != (list_head); pos = pos->next)
/**
* @brief Return the next entry of specific node.
*
* @entry: specific entry.
*
* @return entry_type: next entry of specific entry.
*/
#define sgl_list_next_entry(entry, entry_type, list_node_member) \
sgl_container_of(entry->list_node_member.next, entry_type, list_node_member)
/**
* @brief Return the previous entry of specific node.
*
* @entry: specific entry.
*
* @return entry_type: previous entry of specific entry.
*/
#define sgl_list_prev_entry(entry, entry_type, list_node_member) \
sgl_container_of(entry->list_node_member.prev, entry_type, list_node_member)
/**
* @brief foreach the list inserted in a structure.
*
* @pos: the &struct list_head to use as a loop cursor.
* @list_head: the head for your list.
* @entry_type: type of the struct.
* @list_node_member: member name of the list_node in structure.
*
* @return none
*/
#define sgl_list_for_each_entry(pos, list_head, entry_type, list_node_member) \
for (pos = sgl_container_of((list_head)->next, entry_type, list_node_member); \
&pos->list_node_member != (list_head); \
pos = sgl_container_of(pos->list_node_member.next, entry_type, list_node_member))
/**
* @brief safe foreach the list inserted in a structure.
*
* @pos: the &struct list_head to use as a loop cursor.
* @list_head: the head for your list.
* @entry_type: type of the struct.
* @list_node_member: member name of the list_node in structure.
*
* @return none
*/
#define sgl_list_for_each_entry_safe(pos, n, list_head, entry_type, list_node_member) \
for (pos = (list_head)->next ? sgl_container_of((list_head)->next, entry_type, list_node_member) : NULL, \
n = pos ? sgl_container_of(pos->list_node_member.next, entry_type, list_node_member) : NULL; \
&pos->list_node_member != (list_head); \
pos = n, \
n = pos ? (pos->list_node_member.next ? sgl_container_of(pos->list_node_member.next, entry_type, list_node_member) : NULL) : NULL)
/**
* @brief reverse foreach the list inserted in a structure.
*
* @pos: the &struct list_head to use as a loop cursor.
* @list_head: the head for your list.
* @entry_type: type of the struct.
* @list_node_member: member name of the list_node in structure.
*
* @return none
*/
#define sgl_list_for_each_entry_reverse(pos, list_head, entry_type, list_node_member) \
for (pos = sgl_container_of((list_head)->prev, entry_type, list_node_member); \
&pos->list_node_member != (list_head); \
pos = sgl_container_of(pos->list_node_member.prev, entry_type, list_node_member))
/**
* @brief initialize a list.
*
* @node: inserted node.
*
* @return none
*/
static inline void sgl_list_init(sgl_list_node_t *node)
{
node->next = node;
node->prev = node;
}
/**
* @brief Add a node to the list tail.
*
* @head: head node of the list.
* @node: inserted node.
*
* @return none
*/
static inline void sgl_list_add_node_at_tail(sgl_list_node_t *head, sgl_list_node_t *node)
{
sgl_list_node_t *tail = head->prev;
node->prev = tail;
node->next = head;
tail->next = node;
head->prev = node;
}
/**
* @brief Add a node to the list front.
*
* @head: head node of the list.
* @node: inserted node.
*
* @return none
*/
static inline void sgl_list_add_node_at_front(sgl_list_node_t *head, sgl_list_node_t *node)
{
sgl_list_node_t *front = head->next;
node->prev = head;
node->next = front;
front->prev = node;
head->next = node;
}
/**
* @brief Add a node to the list before a specific node.
* @pos: specific node.
* @node: inserted node.
* @return none
*/
static inline void sgl_list_add_node_at_before(sgl_list_node_t *pos, sgl_list_node_t *node)
{
node->prev = pos->prev;
node->next = pos;
pos->prev->next = node;
pos->prev = node;
}
/**
* @brief Add a node to the list after a specific node.
* @pos: specific node.
* @node: inserted node.
* @return none
*/
static inline void sgl_list_add_node_at_after(sgl_list_node_t *pos, sgl_list_node_t *node)
{
node->next = pos->next;
node->prev = pos;
pos->next->prev = node;
pos->next = node;
}
/**
* @brief Delete a tail node from the list.
*
* @head: head node of the list.
*
* @return none
*/
static inline void sgl_list_del_tail_node(sgl_list_node_t *head)
{
sgl_list_node_t *tail_prev = head->prev->prev;
tail_prev->next = head;
head->prev = tail_prev;
}
/**
* @brief Delete a front node from the list.
*
* @head: head node of the list.
*
* @return none
*/
static inline void sgl_list_del_front_node(sgl_list_node_t *head)
{
sgl_list_node_t *front_next = head->next->next;
front_next->prev = head;
head->next = front_next;
}
/**
* @brief Delete a node from the list.
*
* @node: the node of the list.
*
* @return none
*/
static inline void sgl_list_del_node(sgl_list_node_t *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
/**
* @brief Determine whether the list is empty.
*
* @head: head node of the list.
*
* @return bool: is empty.
*/
static inline bool sgl_list_is_empty(sgl_list_node_t *head)
{
return head->next == head;
}
/**
* @brief Return the next node of specific node.
*
* @node: specific node.
*
* @return list_node*: next node of specific node.
*/
static inline sgl_list_node_t* sgl_list_next_node(sgl_list_node_t *node)
{
return node->next;
}
/**
* @brief Return the previous node of specific node.
*
* @node: specific node.
*
* @return list_node*: previous node of specific node.
*/
static inline sgl_list_node_t* sgl_list_prev_node(sgl_list_node_t *node)
{
return node->prev;
}
#ifdef __cplusplus
}
#endif
#endif // __SGL_LIST_H__

View File

@ -0,0 +1,193 @@
/* source/include/sgl_log.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_LOG_H__
#define __SGL_LOG_H__
#include <sgl_cfgfix.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SGL_LOG_LEVEL_TRACE 0 /**< A lot of logs to give detailed information*/
#define SGL_LOG_LEVEL_INFO 1 /**< Log important events*/
#define SGL_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem*/
#define SGL_LOG_LEVEL_ERROR 3 /**< Only critical issue, when the system may fail*/
#define SGL_LOG_LEVEL_USER 4 /**< Custom logs from the user*/
#define SGL_LOG_LEVEL_NONE 5 /**< Do not log anything*/
#define _SGL_LOG_LEVEL_NUM 6 /**< Number of log levels*/
#if CONFIG_SGL_DEBUG
/**
* @brief sgl log printing function, used to print debugging information. Note that this function
* should only be called in debugging mode, otherwise it may affect system real-time
* performance due to long execution time
*
* @param level: log level, such as, INFO, USER...
* @param format: log content
*
* @return none
*/
void sgl_log(const char *level, const char * format, ...);
/**
* @brief sgl assert handler, used to handle assertions
*
* @param file: file name
* @param func: function name
* @param line: line number
*
* @return none
*/
void sgl_assert_handler(const char *file, const char *func, int line);
#if CONFIG_SGL_LOG_COLOR
#define SGL_LOG_NONE "\033[0m"
#define SGL_LOG_RED "\033[31m"
#define SGL_LOG_GREEN "\033[32m"
#define SGL_LOG_YELLOW "\033[33m"
#define SGL_LOG_BLUE "\033[34m"
#define SGL_LOG_PURPLE "\033[35m"
#define SGL_LOG_CYAN "\033[36m"
#define SGL_LOG_WHITE "\033[37m"
#define SGL_LOG_LIGHT_BLUE "\033[1;34m"
#define SGL_LOG_TRACE_FLAG SGL_LOG_BLUE"[TRACE]"
#define SGL_LOG_INFO_FLAG SGL_LOG_GREEN"[INFO]"
#define SGL_LOG_WARN_FLAG SGL_LOG_YELLOW"[WARN]"
#define SGL_LOG_ERROR_FLAG SGL_LOG_RED"[ERROR]"
#define SGL_LOG_USER_FLAG SGL_LOG_PURPLE"[USER]"
#define SGL_ASSERT_FLAG SGL_LOG_CYAN"[ASSERT]"
#define SGL_DEBUG_TRACE_FLAG SGL_LOG_LIGHT_BLUE"[DEBUG]"
#else
#define SGL_LOG_TRACE_FLAG "[TRACE] "
#define SGL_LOG_INFO_FLAG "[INFO] "
#define SGL_LOG_WARN_FLAG "[WARN] "
#define SGL_LOG_ERROR_FLAG "[ERROR] "
#define SGL_LOG_USER_FLAG "[USER] "
#define SGL_ASSERT_FLAG "[ASSERT] "
#define SGL_DEBUG_TRACE_FLAG "[DEBUG]"
#define SGL_LOG_NONE ""
#endif // !CONFIG_SGL_LOG_COLOR
#ifndef SGL_LOG_TRACE
# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_TRACE
# define SGL_LOG_TRACE(...) sgl_log(SGL_LOG_TRACE_FLAG, __VA_ARGS__)
# else
# define SGL_LOG_TRACE(...) do {} while(0)
# endif
#endif
#ifndef SGL_LOG_INFO
# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_INFO
# define SGL_LOG_INFO(...) sgl_log(SGL_LOG_INFO_FLAG, __VA_ARGS__)
# else
# define SGL_LOG_INFO(...) do {} while(0)
# endif
#endif
#ifndef SGL_LOG_WARN
# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_WARN
# define SGL_LOG_WARN(...) sgl_log(SGL_LOG_WARN_FLAG, __VA_ARGS__)
# else
# define SGL_LOG_WARN(...) do {} while(0)
# endif
#endif
#ifndef SGL_LOG_ERROR
# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_ERROR
# define SGL_LOG_ERROR(...) sgl_log(SGL_LOG_ERROR_FLAG, __VA_ARGS__)
# else
# define SGL_LOG_ERROR(...) do {} while(0)
# endif
#endif
#ifndef SGL_LOG_USER
# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_USER
# define SGL_LOG_USER(...) sgl_log(SGL_LOG_USER_FLAG, __VA_ARGS__)
# else
# define SGL_LOG_USER(...) do {} while(0)
# endif
#endif
#if CONFIG_SGL_LOG_LEVEL < SGL_LOG_LEVEL_NONE
# define SGL_LOG(...) sgl_log(__VA_ARGS__)
#else
# define SGL_LOG(...) do {} while(0)
#endif
#define SGL_ASSERT(cond) do { \
if (!(cond)) { \
sgl_assert_handler(__FILE__, __FUNCTION__, __LINE__); \
} \
} while(0)
#define SGL_ASSERT_INFO(cond, info) do { \
if (!(cond)) { \
SGL_LOG_ERROR("ASSERT: %s", info); \
sgl_assert_handler(__FILE__, __FUNCTION__, __LINE__); \
} \
} while(0)
#else // if no define debug mode macro
#define SGL_LOG_NONE 0
#define SGL_LOG_TRACE(...) do {} while(0)
#define SGL_LOG_INFO(...) do {} while(0)
#define SGL_LOG_WARN(...) do {} while(0)
#define SGL_LOG_ERROR(...) do {} while(0)
#define SGL_LOG_USER(...) do {} while(0)
#define SGL_LOG(...) do {} while(0)
#define SGL_ASSERT(cond) do {} while(0)
#define SGL_ASSERT_INFO(cond, info) do {} while(0)
#endif
#if CONFIG_SGL_DEBUG
#define SGL_DEBUG_TRACE(...) sgl_log(SGL_DEBUG_TRACE_FLAG, __VA_ARGS__)
#else
#define SGL_DEBUG_TRACE(...) do {} while(0)
#endif
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif //!__SGL_LOG_H__

View File

@ -0,0 +1,188 @@
/* source/include/sgl_math.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_MATH_H__
#define __SGL_MATH_H__
#include <sgl_types.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define sgl_min(a, b) ((a) < (b) ? (a) : (b))
#define sgl_min3(a, b, c) (sgl_min(sgl_min((a), (b)), (c)))
#define sgl_min4(a, b, c, d) (sgl_min(sgl_min((a), (b)), sgl_min((c), (d))))
#define sgl_max(a, b) ((a) > (b) ? (a) : (b))
#define sgl_max3(a, b, c) (sgl_max(sgl_max((a), (b)), (c)))
#define sgl_max4(a, b, c, d) (sgl_max(sgl_max((a), (b)), sgl_max((c), (d))))
#define sgl_clamp(val, min, max) (sgl_max(min, (sgl_min((val), (max)))))
#define sgl_abs(x) ((x) > 0 ? (x) : (- (x)))
#define sgl_pow2(x) ((x) * (x))
#define sgl_pow3(x) ((x) * (x) * (x))
#define sgl_pow4(x) ((x) * (x) * (x) * (x))
#define sgl_is_pow2(x) (((x) & ((x) - 1)) == 0)
#define sgl_is_even(x) (((x) & 1) == 0)
#define sgl_is_odd(x) ((x) & 1)
#define sgl_swap(a, b) do { (*a) ^= (*b); (*b) ^= (*a); (*a) ^= (*b); } while (0)
#define sgl_mid(a, b) (((a) + (b)) / 2)
#define SGL_FIXED_SHIFT (10)
#define SGL_FIXED_ONE (1 << SGL_FIXED_SHIFT)
#define SGL_FIXED_MASK (SGL_FIXED_ONE - 1)
#define SGL_SIN_FIXED_ONE (32767)
#define SGL_COS_FIXED_ONE (32767)
/**
* @brief Calculate the sine of an angle
* @param angle: Angle in degrees such 0-359
* @return sine of the angle from sin0_90_table
* @note This function has implemented angle normalization to the range of 0 to 360 degrees.
*/
int32_t sgl_sin(int16_t angle);
/**
* @brief Calculate the cos of an angle
* @param angle: Angle in degrees such 0-359
* @return cos of the angle from sin0_90_table
* @note This function has implemented angle normalization to the range of 0 to 360 degrees.
*/
static inline int32_t sgl_cos(int16_t angle)
{
return sgl_sin(angle + 90);
}
/**
* @brief Calculate x number square root
* @param x: x number
* @retval x number square root
*/
uint16_t sgl_sqrt(uint32_t x);
/**
* @brief Calculate error of the square root for a number.
* @param x The number to calculate the error for.
* @return The error of the square root. [0 ~ 255]
*/
uint8_t sgl_sqrt_error(uint32_t x);
/**
* @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm
* implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm)
*
* @param x: The x coordinate on a circle
* @param y: The y coordinate on a circle
* @return angle
* @note return angle [-32767 ~ 32767]
*/
int32_t sgl_atan2_raw(int x, int y);
/**
* @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm
* implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm)
*
* @param x: The x coordinate on a circle
* @param y: The y coordinate on a circle
* @return angle
* @note return angle [0 ~ 359]
*/
uint16_t sgl_atan2_angle(int x, int y);
/**
* @brief Split the length into n parts, with the weight of each part.
* @param weight: The weight of each part.
* @param count: The count of parts.
* @param length: The length to split.
* @param gap: The gap between each part.
* @param out: The length of each part.
* @note The error accumulation method of Bresenham's algorithm
*/
void sgl_split_len(const uint8_t *weight, int count, int16_t length, int16_t gap, int16_t *out);
/**
* @brief Split the length into n parts, with the weight of each part.
* @param length: The length to split.
* @param count: The count of parts.
* @param gap: The gap between each part.
* @param out: The length of each part.
* @note The average method of Bresenham's algorithm
*/
void sgl_split_len_avg(int length, int count, int16_t gap, int16_t *out);
/**
* @brief Calculate whether the x and y coordinates have a component.
* @param x: The x coordinate on a circle
* @param y: The y coordinate on a circle
* @param xv: The x coordinate of the vector
* @param yv: The y coordinate of the vector
* @return 1: The x and y coordinates have a component. 0: The x and y coordinates do not have a component.
*/
static inline int sgl_xy_has_component( int x, int y, int xv, int yv)
{
return ((x != 0 && ((xv ^ x) < 0)) || (y != 0 && ((yv ^ y) < 0)));
}
/**
* @brief Generate a random number.
* @param none
* @return Random number.
* @note The random number generator is in the range of [0, 32767].
*/
int16_t sgl_rand(void);
/**
* @brief Set the seed of the random number generator.
* @param seed: The seed of the random number generator.
* @return none
*/
void sgl_srand(unsigned int seed);
#ifdef __cplusplus
}
#endif
#endif // !__SGL_MATH_H__

View File

@ -0,0 +1,53 @@
/* source/include/sgl_misc.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_MISC_H__
#define __SGL_MISC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <sgl_cfgfix.h>
#include <stddef.h>
#include <sgl_list.h>
#include <sgl_types.h>
#if (CONFIG_SGL_BOOT_LOGO)
/**
* @brief to show the sgl logo after sgl init
* @param none
* @return none
* @note: you can call this function in your main function to show the sgl logo
*/
void sgl_boot_logo(void);
#endif // ! CONFIG_SGL_BOOT_LOGO
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif // ! __SGL_MISC_H__

View File

@ -0,0 +1,112 @@
/* source/include/sgl_mm.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_MM_H__
#define __SGL_MM_H__
#include <sgl_core.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief memory monitor info
* @total_size: total size of memory
* @free_size: free size of memory
* @used_size: used size of memory
* @used_rate: used rate of memory:
* | 8 bit | 8 bit |
* | int | dec |
*/
typedef struct sgl_mm_monitor {
size_t total_size;
size_t free_size;
size_t used_size;
size_t used_rate;
} sgl_mm_monitor_t;
/**
* @brief initialize memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_init(void *mem_start, size_t len);
/**
* @brief add memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_add_pool(void *mem_start, size_t len);
/**
* @brief memory alloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
*
* @param size request size of memory
*
* @return point to request memory address
*/
void* sgl_malloc(size_t size);
/**
* @brief memory realloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
* @param p the pointer of request size of memory
* @param size request size of memory
*/
void* sgl_realloc(void *p, size_t size);
/**
* @brief memory free
*
* @param p the pointer of request size of memory
*
* @return none
*/
void sgl_free(void *p);
/**
* @brief get memory monitor info
*
* @param none
* @return memory monitor info
*/
sgl_mm_monitor_t sgl_mm_get_monitor(void);
#ifdef __cplusplus
}
#endif
#endif // !__SGL_MM_H__

View File

@ -0,0 +1,79 @@
/* source/include/sgl_theme.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_THEME_H__
#define __SGL_THEME_H__
#include <sgl_cfgfix.h>
#ifdef __cplusplus
extern "C" {
#endif
#if (CONFIG_SGL_THEME_DEFAULT)
#define SGL_THEME_DESKTOP sgl_rgb(255, 255, 255)
#define SGL_THEME_COLOR sgl_rgb(255, 255, 255)
#define SGL_THEME_BG_COLOR sgl_rgb(0, 0, 0)
#define SGL_THEME_BORDER_WIDTH 2
#define SGL_THEME_BORDER_COLOR sgl_rgb(0, 0, 0)
#define SGL_THEME_ALPHA 255
#define SGL_THEME_TEXT_COLOR sgl_rgb(0, 0, 0)
#define SGL_THEME_RADIUS 0
#define SGL_THEME_SCROLL_RADIUS 3
#define SGL_THEME_SCROLL_BG_COLOR sgl_rgb(100, 100, 100)
#define SGL_THEME_SCROLL_FG_COLOR sgl_rgb(200, 200, 200)
#elif (CONFIG_SGL_THEME_DARK)
#define SGL_THEME_DESKTOP sgl_rgb(10, 10, 10)
#define SGL_THEME_COLOR sgl_rgb(50, 50, 50)
#define SGL_THEME_BG_COLOR sgl_rgb(20, 20, 20)
#define SGL_THEME_BORDER_WIDTH 2
#define SGL_THEME_BORDER_COLOR sgl_rgb(200, 200, 200)
#define SGL_THEME_ALPHA 255
#define SGL_THEME_TEXT_COLOR sgl_rgb(200, 200, 200)
#define SGL_THEME_RADIUS 0
#define SGL_THEME_SCROLL_BG_COLOR sgl_rgb(100, 100, 100)
#define SGL_THEME_SCROLL_FG_COLOR sgl_rgb(200, 200, 200)
#elif (CONFIG_SGL_THEME_LIGHT)
#define SGL_THEME_COLOR sgl_rgb(189, 212, 243)
#define SGL_THEME_BG_COLOR sgl_rgb(255, 255, 255)
#define SGL_THEME_BORDER_WIDTH 2
#define SGL_THEME_BORDER_COLOR sgl_rgb(0, 0, 0)
#define SGL_THEME_ALPHA 255
#define SGL_THEME_TEXT_COLOR sgl_rgb(0, 0, 0)
#define SGL_THEME_RADIUS 0
#define SGL_THEME_SCROLL_BG_COLOR sgl_rgb(100, 100, 100)
#define SGL_THEME_SCROLL_FG_COLOR sgl_rgb(200, 200, 200)
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,337 @@
/* source/include/sgl_types.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_TYPES_H__
#define __SGL_TYPES_H__
#include <stdint.h>
#include <stdbool.h>
#include <sgl_cfgfix.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get the offset of internal members of the structure
*
* @struct_t: structure typedef
* @member: member in structure
*
* @return offset of member in the structure
*/
#define sgl_offsetof(struct_t, member) ((size_t)&((struct_t*)0)->member)
/**
* @brief Get the address of the structure instance.
*
* @ptr: address of the structure member.
* @type: type of the structure.
* @member: member name of the ptr in structure.
* @return pointer to address of structure
*/
#define sgl_container_of(ptr, type, member) ((type *)((char *)ptr - sgl_offsetof(type, member)))
#ifndef SGL_ARRAY_SIZE
#define SGL_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#endif
#define SGL_ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
#define SGL_ROUND_UP(x, round) ((((x) + ((round) - 1)) / (round)) * (round))
#define SGL_UNUSED(x) (void)(x)
#define SGL_POS_INVALID (0xefff)
#define SGL_POS_MAX (8192)
#define SGL_POS_MIN (-8192)
#define SGL_RADIUS_INVALID (0xFFF)
#define SGL_AREA_MAX {.x1 = SGL_POS_MIN, .y1 = SGL_POS_MIN, .x2 = SGL_POS_MAX, .y2 = SGL_POS_MAX}
#define SGL_AREA_INVALID {.x1 = SGL_POS_MAX, .y1 = SGL_POS_MAX, .x2 = SGL_POS_MIN, .y2 = SGL_POS_MIN}
#define SGL_WIDTH_INVALID (-1)
#define SGL_WIDTH_MAX (8192)
#define SGL_WIDTH_MIN (0)
#define SGL_HEIGHT_INVALID (-1)
#define SGL_HEIGHT_MAX (8192)
#define SGL_HEIGHT_MIN (0)
#define SGL_DIRECT_HORIZONTAL (0)
#define SGL_DIRECT_VERTICAL (1)
#define SGL_ALPHA_MAX (255)
#define SGL_ALPHA_MIN (0)
#define SGL_ALPHA_NUM (256)
#define SGL_STYLE_OK (0)
#define SGL_STYLE_FAILED (UINT32_MAX)
#define SGL_STYLE_INVALID (UINT32_MAX)
#define SGL_COLOR_RGB332 (8)
#define SGL_COLOR_RGB565 (16)
#define SGL_COLOR_RGB888 (24)
#define SGL_COLOR_ARGB8888 (32)
/* the pixmap format */
#define SGL_PIXMAP_FMT_NONE (0)
#define SGL_PIXMAP_FMT_RGB332 (1)
#define SGL_PIXMAP_FMT_ARGB2222 (2)
#define SGL_PIXMAP_FMT_RGB565 (3)
#define SGL_PIXMAP_FMT_ARGB4444 (4)
#define SGL_PIXMAP_FMT_RGB888 (5)
#define SGL_PIXMAP_FMT_ARGB8888 (6)
#define SGL_PIXMAP_FMT_RLE_RGB332 (7)
#define SGL_PIXMAP_FMT_RLE_ARGB2222 (8)
#define SGL_PIXMAP_FMT_RLE_RGB565 (9)
#define SGL_PIXMAP_FMT_RLE_ARGB4444 (10)
#define SGL_PIXMAP_FMT_RLE_RGB888 (11)
#define SGL_PIXMAP_FMT_RLE_ARGB8888 (12)
#define SGL_PIXMAP_FMT_MAX (13)
#ifdef __GNUC__ /* gcc compiler */
#ifndef likely
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif
#define sgl_weak_fn __attribute__((weak))
#define sgl_section(sec) __attribute__((section(#sec)))
#elif defined(__clang__) /* clang compiler */
#ifndef likely
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif
#define sgl_weak_fn __attribute__((weak))
#define sgl_section(sec) __attribute__((section(#sec)))
#elif defined(__CC_ARM) /* RealView compiler (Keil ARMCC) */
#ifndef likely
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif
#define sgl_weak_fn __weak
#define sgl_section(sec) __attribute__((section(#sec)))
#elif defined(__ICCARM__) /* IAR compiler */
#ifndef likely
# define likely(x) __iar_builtin_expect(!!(x), 1)
# define unlikely(x) __iar_builtin_expect(!!(x), 0)
#endif
#define sgl_weak_fn __weak
#define sgl_section(sec) __section(#sec)
#elif defined(_MSC_VER) /* MSVC compiler */
#ifndef likely
# define likely(x) (x)
# define unlikely(x) (x)
#endif
#define sgl_weak_fn __declspec(selectany)
#elif defined(__MINGW32__) /* MinGW compiler */
#ifndef likely
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif
#define sgl_weak_fn __attribute__((weak))
#define sgl_section(sec) __attribute__((section(#sec)))
#else /* others compiler */
#ifndef likely
# define likely(x) (x)
# define unlikely(x) (x)
#endif
#warning "Weak linkage not supported for this compiler"
#endif
#define sgl_check_ptr_break(ptr) if (unlikely((ptr) == NULL)) { SGL_LOG_ERROR("Function: %s, Line: %d, "#ptr" is NULL", __func__, __LINE__); return;}
#define sgl_check_ptr_return(ptr, r) if (unlikely((ptr) == NULL)) { SGL_LOG_ERROR("Function: %s, Line: %d, "#ptr" is NULL", __func__, __LINE__); return (r);}
/**
* @brief Run once function
* @note you must sure the statement is thread safe
*/
#define SGL_RUN_ONCE(statement) do { \
static bool _run_once_flag = false; \
if (unlikely(_run_once_flag == false)){ \
statement; \
_run_once_flag = true; \
} \
} while(0)
// prototype: sgl_rgb(uint8_t r, uint8_t g, uint8_t b)
#if (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_ARGB8888 || CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB888)
#define sgl_rgb(r,g,b) (sgl_color_t){ .ch.blue = (b), \
.ch.green = (g), \
.ch.red = (r),}
#define sgl_rgb222_to_color(rgb222) (sgl_color_t){ .ch.blue = ((((rgb222) >> 0) & 0x03) << 6), \
.ch.green = ((((rgb222) >> 2) & 0x03) << 6), \
.ch.red = ((((rgb222) >> 4) & 0x03) << 6),}
#define sgl_rgb332_to_color(rgb332) (sgl_color_t){ .ch.blue = ((((rgb332) >> 0) & 0x03) << 6), \
.ch.green = ((((rgb332) >> 2) & 0x07) << 5), \
.ch.red = ((((rgb332) >> 5) & 0x07) << 5),}
#define sgl_rgb444_to_color(rgb444) (sgl_color_t){ .ch.blue = ((((rgb444) >> 0) & 0xF) << 4), \
.ch.green = ((((rgb444) >> 4) & 0xF) << 4), \
.ch.red = ((((rgb444) >> 8) & 0xF) << 4),}
#define sgl_rgb565_to_color(rgb565) (sgl_color_t){ .ch.blue = ((((rgb565) >> 0) & 0x1F) << 3), \
.ch.green = ((((rgb565) >> 5) & 0x3F) << 2), \
.ch.red = ((((rgb565) >> 11) & 0x1F) << 3),}
#define sgl_rgb888_to_color(rgb888) (sgl_color_t){ .ch.blue = ((rgb888) >> 0), \
.ch.green = ((rgb888) >> 8), \
.ch.red = ((rgb888) >> 16),}
#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB565)
#define sgl_rgb(r,g,b) (sgl_color_t){ .ch.blue = (b) >> 3, \
.ch.green = (g) >> 2, \
.ch.red = (r) >> 3,}
#define sgl_rgb222_to_color(rgb222) (sgl_color_t){ .ch.blue = ((((rgb222) >> 0) & 0x03) << 3), \
.ch.green = ((((rgb222) >> 2) & 0x03) << 4), \
.ch.red = ((((rgb222) >> 4) & 0x03) << 3),}
#define sgl_rgb332_to_color(rgb332) (sgl_color_t){ .ch.blue = ((((rgb332) >> 0) & 0x03) << 3), \
.ch.green = ((((rgb332) >> 2) & 0x03) << 2), \
.ch.red = ((((rgb332) >> 5) & 0x03) << 2),}
#define sgl_rgb444_to_color(rgb444) (sgl_color_t){ .ch.blue = ((((rgb444) >> 0) & 0xF) << 1), \
.ch.green = ((((rgb444) >> 4) & 0xF) << 2), \
.ch.red = ((((rgb444) >> 8) & 0xF) << 1),}
#define sgl_rgb565_to_color(rgb565) (sgl_color_t){ .ch.blue = ((rgb565) >> 0) & 0x1F, \
.ch.green = ((rgb565) >> 5) & 0x3F, \
.ch.red = ((rgb565) >> 11) & 0x1F,}
#define sgl_rgb888_to_color(rgb888) (sgl_color_t){ .ch.blue = (((rgb888) >> 0) >> 3), \
.ch.green = (((rgb888) >> 8) >> 2), \
.ch.red = (((rgb888) >> 16) >> 3),}
#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB332)
#define sgl_rgb(r,g,b) (sgl_color_t){ .ch.blue = (b >> 6), \
.ch.green = (g >> 5), \
.ch.red = (r >> 5),}
#define sgl_rgb222_to_color(rgb222) (sgl_color_t){ .ch.blue = ((((rgb222) >> 0) & 0x03) >> 0), \
.ch.green = ((((rgb222) >> 2) & 0x03) >> 1), \
.ch.red = ((((rgb222) >> 4) & 0x03) >> 1),}
#define sgl_rgb332_to_color(rgb332) (sgl_color_t){ .ch.blue = (((rgb332) >> 0) & 0x03), \
.ch.green = (((rgb332) >> 3) & 0x07), \
.ch.red = (((rgb332) >> 5) & 0x07),}
#define sgl_rgb444_to_color(rgb444) (sgl_color_t){ .ch.blue = ((((rgb444) >> 0) & 0xF) >> 2), \
.ch.green = ((((rgb444) >> 4) & 0xF) >> 1), \
.ch.red = ((((rgb444) >> 8) & 0xF) >> 1),}
#define sgl_rgb565_to_color(rgb565) (sgl_color_t){ .ch.blue = ((((rgb565) >> 0) & 0x1F) >> 3), \
.ch.green = ((((rgb565) >> 5) & 0x3F) >> 3), \
.ch.red = ((((rgb565) >> 11) & 0x1F) >> 2),}
#define sgl_rgb888_to_color(rgb888) (sgl_color_t){ .ch.blue = (((rgb888) >> 0)>> 6), \
.ch.green = (((rgb888) >> 8) >> 5), \
.ch.red = (((rgb888) >> 16) >> 6),}
#endif
/**
* Define some basic colors
*/
#define SGL_COLOR_RED sgl_rgb(0xFF, 0, 0)
#define SGL_COLOR_GREEN sgl_rgb(0, 0xFF, 0)
#define SGL_COLOR_BLUE sgl_rgb(0, 0, 0xFF)
#define SGL_COLOR_WHITE sgl_rgb(0xFF, 0xFF, 0xFF)
#define SGL_COLOR_BLACK sgl_rgb(0, 0, 0)
#define SGL_COLOR_CYAN sgl_rgb(0, 0xFF, 0xFF)
#define SGL_COLOR_MAGENTA sgl_rgb(0xFF, 0, 0xFF)
#define SGL_COLOR_YELLOW sgl_rgb(0xFF, 0xFF, 0)
#define SGL_COLOR_GRAY sgl_rgb(0x80, 0x80, 0x80)
#define SGL_COLOR_DARK_GRAY sgl_rgb(0x40, 0x40, 0x40)
#define SGL_COLOR_LIGHT_GRAY sgl_rgb(0xC0, 0xC0, 0xC0)
#define SGL_COLOR_BRIGHT_PURPLE sgl_rgb(0xFF, 0x00, 0xFF)
#define SGL_COLOR_BRIGHT_BLUE sgl_rgb(0x00, 0xFF, 0xFF)
#define SGL_COLOR_ORANGE sgl_rgb(0xFF, 0xA5, 0x00)
#define SGL_COLOR_DARK_ORANGE sgl_rgb(0xFF, 0x8C, 0x00)
#define SGL_COLOR_RED_ORANGE sgl_rgb(0xFF, 0x45, 0x00)
#define SGL_COLOR_GOLD sgl_rgb(0xFF, 0xD7, 0x00)
#define SGL_COLOR_GOLDENROD sgl_rgb(0xDA, 0xA5, 0x20)
#define SGL_COLOR_BROWN sgl_rgb(0xA5, 0x2A, 0x2A)
#define SGL_COLOR_SADDLE_BROWN sgl_rgb(0x8B, 0x45, 0x13)
#define SGL_COLOR_TOMATO sgl_rgb(0xFF, 0x63, 0x47)
#define SGL_COLOR_CORAL sgl_rgb(0xFF, 0x7F, 0x50)
#define SGL_COLOR_SALMON sgl_rgb(0xFA, 0x80, 0x72)
#define SGL_COLOR_LIME sgl_rgb(0x32, 0xCD, 0x32)
#define SGL_COLOR_OLIVE sgl_rgb(0x80, 0x80, 0x00)
#define SGL_COLOR_DARK_OLIVE_GREEN sgl_rgb(0x55, 0x6B, 0x2F)
#define SGL_COLOR_FOREST_GREEN sgl_rgb(0x22, 0x8B, 0x2F)
#define SGL_COLOR_DARK_GREEN sgl_rgb(0x00, 0x64, 0x00)
#define SGL_COLOR_LAWN_GREEN sgl_rgb(0x7C, 0xFC, 0x00)
#define SGL_COLOR_CHARTREUSE sgl_rgb(0x7F, 0xFF, 0x00)
#define SGL_COLOR_YELLOW_GREEN sgl_rgb(0x9A, 0xCD, 0x32)
#define SGL_COLOR_SPRING_GREEN sgl_rgb(0x00, 0xFF, 0x7F)
#define SGL_COLOR_DEEP_SKY_BLUE sgl_rgb(0x00, 0xBF, 0xFF)
#define SGL_COLOR_DODGER_BLUE sgl_rgb(0x1E, 0x90, 0xFF)
#define SGL_COLOR_ROYAL_BLUE sgl_rgb(0x41, 0x69, 0xE1)
#define SGL_COLOR_MIDNIGHT_BLUE sgl_rgb(0x19, 0x19, 0x70)
#define SGL_COLOR_NAVY sgl_rgb(0x00, 0x00, 0x80)
#define SGL_COLOR_TEAL sgl_rgb(0x00, 0x80, 0x80)
#define SGL_COLOR_DARK_CYAN sgl_rgb(0x00, 0x8B, 0x8B)
#define SGL_COLOR_LIGHT_SEA_GREEN sgl_rgb(0x20, 0xB2, 0xAA)
#define SGL_COLOR_CADET_BLUE sgl_rgb(0x5F, 0x9E, 0xA0)
#define SGL_COLOR_INDIGO sgl_rgb(0x4B, 0x00, 0x82)
#define SGL_COLOR_VIOLET sgl_rgb(0xEE, 0x82, 0xEE)
#define SGL_COLOR_DARK_VIOLET sgl_rgb(0x94, 0x00, 0xD3)
#define SGL_COLOR_MEDIUM_VIOLET_RED sgl_rgb(0xC7, 0x15, 0x85)
#define SGL_COLOR_PINK sgl_rgb(0xFF, 0xC0, 0xCB)
#define SGL_COLOR_HOT_PINK sgl_rgb(0xFF, 0x69, 0xB4)
#define SGL_COLOR_DEEP_PINK sgl_rgb(0xFF, 0x14, 0x93)
#define SGL_COLOR_PLUM sgl_rgb(0xDD, 0xA0, 0xDD)
#define SGL_COLOR_ORCHID sgl_rgb(0xDA, 0x70, 0xD6)
#define SGL_COLOR_TAN sgl_rgb(0xD2, 0xB4, 0x8C)
#define SGL_COLOR_WHEAT sgl_rgb(0xF5, 0xDE, 0xB3)
#define SGL_COLOR_SAND sgl_rgb(0xC2, 0xB2, 0x90)
#define SGL_COLOR_BEIGE sgl_rgb(0xF5, 0xF5, 0xDC)
#define SGL_COLOR_IVORY sgl_rgb(0xFF, 0xFF, 0xF0)
#define SGL_COLOR_LAVENDER sgl_rgb(0xE6, 0xE6, 0xFA)
#define SGL_COLOR_MISTY_ROSE sgl_rgb(0xFF, 0xE4, 0xE1)
#define SGL_COLOR_SEASHELL sgl_rgb(0xFF, 0xF5, 0xEE)
#define SGL_COLOR_FLORAL_WHITE sgl_rgb(0xFF, 0xFA, 0xF0)
#ifdef __cplusplus
}
#endif
#endif //__SGL_TYPES_H__

117
User/system/sgl/lm.cfg Normal file
View File

@ -0,0 +1,117 @@
# source/lm.cfg
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
CONFIG_SGL_FBDEV_PIXEL_DEPTH
choices = 8, 16, 24, 32
default = 32
CONFIG_SGL_FBDEV_ROTATION
choices = 0, 90, 180, 270
default = 0
CONFIG_SGL_FBDEV_RUNTIME_ROTATION
choices = n, y
default = n
CONFIG_SGL_USE_FBDEV_VRAM
choices = n, y
default = n
CONFIG_SGL_SYSTICK_MS
choices = [10, 1000]
default = 10
# this value must be power of 2, such as 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536
CONFIG_SGL_EVENT_QUEUE_SIZE
choices = [16, 65536]
default = 32
CONFIG_SGL_EVENT_CLICK_INTERVAL
choices = [5, 100]
default = 10
CONFIG_SGL_DIRTY_AREA_NUM_MAX
choices = [8, 255]
default = 16
CONFIG_SGL_COLOR16_SWAP
choices = n, y
default = n
CONFIG_SGL_PIXMAP_BILINEAR_INTERP
choices = n, y
default = n
CONFIG_SGL_ANIMATION
choices = n, y
default = n
CONFIG_SGL_DEBUG
choices = n, y
default = n
CONFIG_SGL_LOG_COLOR
choices = n, y
default = n
depends = CONFIG_SGL_DEBUG
CONFIG_SGL_LOG_LEVEL
choices = 0, 1, 2, 3, 4, 5, 6
default = 0
depends = CONFIG_SGL_DEBUG
CONFIG_SGL_OBJ_USE_NAME
choices = n, y
default = n
CONFIG_SGL_FONT_COMPRESSED
choices = n, y
default = n
CONFIG_SGL_FONT_SMALL_TABLE
choices = n, y
default = n
CONFIG_SGL_LABEL_ROTATION
choices = n, y
default = n
CONFIG_SGL_BOOT_LOGO
choices = n, y
default = y
CONFIG_SGL_THEME_DARK
choices = n, y
default = n
PATH += ./ include
CFLAG-$(CONFIG_SGL_DEBUG) += -g
include "core/lm.cfg"
include "mm/lm.cfg"
include "draw/lm.cfg"
include "widgets/lm.cfg"
include "fonts/lm.cfg"

View File

@ -0,0 +1,52 @@
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
if(${SGL_HEAP_ALGO} STREQUAL "tlsf")
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/tlsf/tlsf.c
${CMAKE_CURRENT_LIST_DIR}/tlsf/sgl_mm.c
)
endif()
if(${SGL_HEAP_ALGO} STREQUAL "lwmem")
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/lwmem/lwmem.c
${CMAKE_CURRENT_LIST_DIR}/lwmem/sgl_mm.c
)
endif()
if(${SGL_HEAP_ALGO} STREQUAL "bump")
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/bump/sgl_mm.c
)
endif()
if(${SGL_HEAP_ALGO} STREQUAL "other")
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/other/sgl_mm.c
)
endif()

View File

@ -0,0 +1,137 @@
/* source/mm/bump/sgl_mm.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
/**
* WARNING: This memory allocator is not support free operation, if you free the memory, the memory will be corrupted.
*/
#include <stdint.h>
#include <sgl_mm.h>
#include <sgl_log.h>
#include <sgl_cfgfix.h>
#include <stdlib.h>
#include <string.h>
static sgl_mm_monitor_t mem = {
.total_size = 0,
.free_size = 0,
.used_size = 0,
};
static void *bump_mem_start = NULL;
static size_t bump_mem_offset = 0;
/**
* @brief initialize memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_init(void *mem_start, size_t len)
{
bump_mem_start = mem_start;
mem.total_size += len;
mem.free_size = mem.total_size;
}
/**
* @brief add memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_add_pool(void *mem_start, size_t len)
{
SGL_UNUSED(mem_start);
SGL_UNUSED(len);
SGL_LOG_ERROR("sgl_mm_add_pool is not supported");
SGL_ASSERT(0);
}
/**
* @brief memory alloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
*
* @param size request size of memory
*
* @return point to request memory address
*/
void* sgl_malloc(size_t size)
{
uint8_t *ptr = (uint8_t*)bump_mem_start;
if (size == 0 || (bump_mem_offset + size) > mem.total_size) {
return NULL;
}
ptr += bump_mem_offset;
bump_mem_offset += size;
mem.used_size += size;
mem.free_size -= size;
return (void*)ptr;
}
/**
* @brief memory realloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
* @param p the pointer of request size of memory
* @param size request size of memory
*/
void* sgl_realloc(void *p, size_t size)
{
SGL_UNUSED(p);
SGL_UNUSED(size);
SGL_LOG_ERROR("sgl_realloc is not supported");
SGL_ASSERT(0);
return NULL;
}
/**
* @brief memory free
*
* @param p the pointer of request size of memory
*
* @return none
*/
void sgl_free(void *p)
{
SGL_UNUSED(p);
SGL_LOG_ERROR("sgl_free is not supported");
SGL_ASSERT(0);
}
sgl_mm_monitor_t sgl_mm_get_monitor(void)
{
int integer = (mem.used_size * 100) / mem.total_size;
int decimal = (mem.used_size * 10000) / mem.total_size - (integer * 100);
mem.used_rate = integer << 8 | decimal;
mem.free_size = mem.total_size - mem.used_size;
return mem;
}

66
User/system/sgl/mm/lm.cfg Normal file
View File

@ -0,0 +1,66 @@
# source/mm/lm.cfg
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
# Memory management
# Description:
# - tlsf
# A dynamic, fragmentation-resistant allocator designed for real-time and embedded systems
# (e.g., RTOS, MCUs with moderate RAM). It balances speed, memory utilization, and low fragmentation.
#
# - lwmem
# A lightweight, MCU-optimized allocator (developed for embedded systems) that prioritizes minimal
# resource usage (RAM/ROM) while supporting basic dynamic allocation/deallocation.
#
# - bump
# The simplest and fastest memory allocator, often called a "linear allocator" or "stack allocator"
# (though not to be confused with the program stack). It manages a single contiguous block of
# memory (a memory pool) with a single pointer (offset) that "bumps forward" to allocate memory.
#
# - other
# Other memory allocation algorithms, you can implement your own memory allocation algorithm.
# If you want to use dynamic memory allocation algorithm, you can consider it as an option
CONFIG_SGL_HEAP_ALGO
choices = tlsf, lwmem, bump, other
default = lwmem
CONFIG_SGL_FL_INDEX_MAX
choices = [10, 31]
depends = CONFIG_SGL_HEAP_ALGO
default = 20
# Memory size is Byte
CONFIG_SGL_HEAP_MEMORY_SIZE
choices = [1, 10000000]
depends = CONFIG_SGL_HEAP_ALGO
default = 10240
SRC-$(CONFIG_SGL_HEAP_ALGO == tlsf) += tlsf/tlsf.c tlsf/sgl_mm.c
SRC-$(CONFIG_SGL_HEAP_ALGO == lwmem) += lwmem/lwmem.c lwmem/sgl_mm.c
SRC-$(CONFIG_SGL_HEAP_ALGO == bump) += bump/sgl_mm.c
SRC-$(CONFIG_SGL_HEAP_ALGO == other) += other/sgl_mm.c

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,160 @@
/**
* \file lwmem.h
* \brief Lightweight dynamic memory manager
*/
/*
* Copyright (c) 2024 Tilen MAJERLE
*
* 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.
*
* This file is part of LwMEM - Lightweight dynamic memory manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.2.1
*/
#ifndef LWMEM_HDR_H
#define LWMEM_HDR_H
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include "lwmem_opt.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* \defgroup LWMEM Lightweight dynamic memory manager
* \brief Lightweight dynamic memory manager
* \{
*/
/**
* \brief Get size of statically allocated array
* \param[in] x: Object to get array size of
* \return Number of elements in array
*/
#define LWMEM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
/**
* \brief Memory block structure
*/
typedef struct lwmem_block {
struct lwmem_block* next; /*!< Next free memory block on linked list.
Set to \ref LWMEM_BLOCK_ALLOC_MARK when block is allocated and in use */
size_t size; /*!< Size of block, including metadata part.
MSB bit is set to `1` when block is allocated and in use,
or `0` when block is considered free */
} lwmem_block_t;
/**
* \brief Statistics structure
*/
typedef struct {
uint32_t mem_size_bytes; /*!< Total memory size of all regions combined */
uint32_t mem_available_bytes; /*!< Free memory available for allocation */
uint32_t minimum_ever_mem_available_bytes; /*!< Minimum amount of total free memory there has been
in the heap since the system booted. */
uint32_t nr_alloc; /*!< Number of all allocated blocks in single instance */
uint32_t nr_free; /*!< Number of frees in the LwMEM instance */
} lwmem_stats_t;
/**
* \brief LwMEM main structure
*/
typedef struct lwmem {
size_t mem_available_bytes; /*!< Memory size available for allocation */
#if LWMEM_CFG_FULL
lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */
lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */
size_t mem_regions_count; /*!< Number of regions used for allocation */
#else
uint8_t* mem_next_available_ptr; /*!< Pointer for next allocation */
uint8_t is_initialized; /*!< Set to `1` when initialized */
#endif
#if LWMEM_CFG_OS || __DOXYGEN__
LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */
#endif /* LWMEM_CFG_OS || __DOXYGEN__ */
#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__
lwmem_stats_t stats; /*!< Statistics */
#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */
#if defined(LWMEM_DEV) && !__DOXYGEN__
lwmem_block_t start_block_first_use; /*!< Value of start block for very first time.
This is used only during validation process and is removed in final use */
#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */
} lwmem_t;
/**
* \brief Memory region descriptor
*/
typedef struct {
void* start_addr; /*!< Region start address */
size_t size; /*!< Size of region in units of bytes */
} lwmem_region_t;
size_t lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions);
void* lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size);
void* lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size);
#if LWMEM_CFG_FULL || __DOXYGEN__
void* lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size);
int lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size);
void lwmem_free_ex(lwmem_t* lwobj, void* const ptr);
void lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr);
size_t lwmem_get_size_ex(lwmem_t* lwobj, void* ptr);
#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */
#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__
void lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats);
void lwmem_get_size(lwmem_stats_t* stats);
#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */
size_t lwmem_assignmem(const lwmem_region_t* regions);
void* lwmem_malloc(size_t size);
void* lwmem_calloc(size_t nitems, size_t size);
#if LWMEM_CFG_FULL || __DOXYGEN__
void* lwmem_realloc(void* ptr, size_t size);
int lwmem_realloc_s(void** ptr2ptr, size_t size);
void lwmem_free(void* ptr);
void lwmem_free_s(void** ptr2ptr);
size_t lwmem_get_size(void* ptr);
#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */
#if defined(LWMEM_DEV) && !__DOXYGEN__
unsigned char lwmem_debug_create_regions(lwmem_region_t** regs_out, size_t count, size_t size);
void lwmem_debug_save_state(void);
void lwmem_debug_restore_to_saved(void);
void lwmem_debug_print(unsigned char print_alloc, unsigned char print_free);
void lwmem_debug_test_region(void* region_start, size_t region_size, uint8_t** region_start_calc,
size_t* region_size_calc);
#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */
/**
* \}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWMEM_HDR_H */

View File

@ -0,0 +1,156 @@
/**
* \file lwmem_opt.h
* \brief LwMEM options
*/
/*
* Copyright (c) 2024 Tilen MAJERLE
*
* 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.
*
* This file is part of LwMEM - Lightweight dynamic memory manager library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.2.1
*/
#ifndef LWMEM_OPT_HDR_H
#define LWMEM_OPT_HDR_H
/* Uncomment to ignore user options (or set macro in compiler flags) */
/* #define LWMEM_IGNORE_USER_OPTS */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* \defgroup LWMEM_OPT Configuration
* \brief LwMEM options
* \{
*/
/**
* \brief Enables `1` or disables `0` operating system support in the library
*
* \note When `LWMEM_CFG_OS` is enabled, user must implement functions in \ref LWMEM_SYS group.
*/
#ifndef LWMEM_CFG_OS
#define LWMEM_CFG_OS 0
#endif
/**
* \brief Mutex handle type
*
* \note This value must be set in case \ref LWMEM_CFG_OS is set to `1`.
* If data type is not known to compiler, include header file with
* definition before you define handle type
*/
#ifndef LWMEM_CFG_OS_MUTEX_HANDLE
#define LWMEM_CFG_OS_MUTEX_HANDLE void*
#endif
/**
* \brief Number of bits to align memory address and memory size
*
* Some CPUs do not offer unaligned memory access (Cortex-M0 as an example)
* therefore it is important to have alignment of data addresses and potentialy length of data
*
* \note This value must be a power of `2` for number of bytes.
* Usually alignment of `4` bytes fits to all processors.
*/
#ifndef LWMEM_CFG_ALIGN_NUM
#define LWMEM_CFG_ALIGN_NUM 4
#endif
/**
* \brief Enables `1` or disables `0` full memory management support.
*
* When enabled (default config), library supports allocation, reallocation and freeing of the memory.
* - Memory [c]allocation
* - Memory reallocation
* - Memory allocation in user defined memory regions
* - Memory freeing
*
* When disabled, library only supports allocation and does not provide any other service.
* - Its purpose is for memory allocation at the start of firmware initialization only
*
* \note When disabled, statistics functionaltiy is not available
* and only one region is supported (for now, may be updated later).
* API to allocate memory remains the same as for full configuration.
*/
#ifndef LWMEM_CFG_FULL
#define LWMEM_CFG_FULL 1
#endif
/**
* \brief Enables `1` or disables `0` memory cleanup on free operation (or realloc).
*
* It resets unused memory to `0x00` and prevents other applications seeing old data.
* It is disabled by default since it has performance penalties.
*/
#ifndef LWMEM_CFG_CLEAN_MEMORY
#define LWMEM_CFG_CLEAN_MEMORY 0
#endif
/**
* \brief Enables `1` or disables `0` statistics in the library
*
*/
#ifndef LWMEM_CFG_ENABLE_STATS
#define LWMEM_CFG_ENABLE_STATS 0
#endif
/**
* \brief Memory set function
*
* \note Function footprint is the same as \ref memset
*/
#ifndef LWMEM_MEMSET
#define LWMEM_MEMSET(dst, val, len) memset((dst), (val), (len))
#endif
/**
* \brief Memory copy function
*
* \note Function footprint is the same as \ref memcpy
*/
#ifndef LWMEM_MEMCPY
#define LWMEM_MEMCPY(dst, src, len) memcpy((dst), (src), (len))
#endif
/**
* \brief Memory move function
*
* \note Function footprint is the same as \ref memmove
*/
#ifndef LWMEM_MEMMOVE
#define LWMEM_MEMMOVE(dst, src, len) memmove((dst), (src), (len))
#endif
/**
* \}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LWMEM_OPT_HDR_H */

View File

@ -0,0 +1,137 @@
/* source/mm/lwmem/sgl_mm.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <stdint.h>
#include <sgl_mm.h>
#include "lwmem.h"
#include <sgl_log.h>
#include <sgl_cfgfix.h>
static sgl_mm_monitor_t mem = {
.total_size = 0,
.free_size = 0,
.used_size = 0,
};
/**
* @brief initialize memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_init(void *mem_start, size_t len)
{
lwmem_region_t lwmem[] = {
{.start_addr = mem_start, .size = len,},
{ NULL, 0 },
};
lwmem_assignmem(lwmem);
mem.total_size += len;
}
/**
* @brief add memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_add_pool(void *mem_start, size_t len)
{
lwmem_region_t lwmem[] = {
{.start_addr = mem_start, .size = len,},
{ NULL, 0 },
};
lwmem_assignmem(lwmem);
mem.total_size += len;
}
/**
* @brief memory alloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
*
* @param size request size of memory
*
* @return point to request memory address
*/
void* sgl_malloc(size_t size)
{
void *ret = lwmem_malloc(size);
if(ret == NULL) {
SGL_LOG_ERROR("out of memory");
return NULL;
}
mem.used_size += lwmem_get_size(ret);
return ret;
}
/**
* @brief memory realloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
* @param p the pointer of request size of memory
* @param size request size of memory
*/
void* sgl_realloc(void *p, size_t size)
{
void *ret = lwmem_realloc(p, size);
if(ret == NULL) {
SGL_LOG_ERROR("out of memory");
return NULL;
}
mem.used_size += size;
return ret;
}
/**
* @brief memory free
*
* @param p the pointer of request size of memory
*
* @return none
*/
void sgl_free(void *p)
{
mem.used_size -= lwmem_get_size(p);
lwmem_free(p);
}
sgl_mm_monitor_t sgl_mm_get_monitor(void)
{
int integer = (mem.used_size * 100) / mem.total_size;
int decimal = (mem.used_size * 10000) / mem.total_size - (integer * 100);
mem.used_rate = integer << 8 | decimal;
mem.free_size = mem.total_size - mem.used_size;
return mem;
}

View File

@ -0,0 +1,141 @@
/* source/mm/other/sgl_mm.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
/**
* @file sgl_mm.c
* @brief SGL Memory Management - Default (weak) implementations
*
* @warning DO NOT MODIFY THIS FILE!
*
* This file provides default weak implementations of the memory management
* functions. These functions use the standard C library (malloc/free/realloc).
*
* To customize memory management for your platform:
* 1. Create your own implementation file in your project
* 2. Define the same functions WITHOUT the weak attribute
* 3. Your implementation will automatically override these defaults
*
* Functions available for override:
* - void* sgl_mm_alloc(size_t size)
* - void sgl_mm_free(void *ptr)
* - void* sgl_mm_realloc(void *ptr, size_t size)
*
* Example (in your application code):
* @code
* void* sgl_mm_alloc(size_t size) {
* return my_custom_allocator(size);
* }
* @endcode
*/
#include <stdint.h>
#include <sgl_mm.h>
#include <sgl_log.h>
#include <sgl_cfgfix.h>
#include <stdlib.h>
#include <string.h>
static sgl_mm_monitor_t mem = {
.total_size = 0,
.free_size = 0,
.used_size = 0,
};
/**
* @brief initialize memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_init(void *mem_start, size_t len)
{
mem.total_size += len;
}
/**
* @brief add memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_add_pool(void *mem_start, size_t len)
{
mem.total_size += len;
}
/**
* @brief memory alloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
*
* @param size request size of memory
*
* @return point to request memory address
*/
sgl_weak_fn void* sgl_malloc(size_t size)
{
void *p = malloc(size);
memset(p, 0, size);
return p;
}
/**
* @brief memory realloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
* @param p the pointer of request size of memory
* @param size request size of memory
*/
sgl_weak_fn void* sgl_realloc(void *p, size_t size)
{
return realloc(p, size);
}
/**
* @brief memory free
*
* @param p the pointer of request size of memory
*
* @return none
*/
sgl_weak_fn void sgl_free(void *p)
{
//mem.used_size -= ;
free(p);
}
sgl_mm_monitor_t sgl_mm_get_monitor(void)
{
int integer = (mem.used_size * 100) / mem.total_size;
int decimal = (mem.used_size * 10000) / mem.total_size - (integer * 100);
mem.used_rate = integer << 8 | decimal;
mem.free_size = mem.total_size - mem.used_size;
return mem;
}

View File

@ -0,0 +1,128 @@
/* source/mm/tlsf/sgl_mm.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 "tlsf.h"
#include <stdint.h>
#include <sgl_mm.h>
#include <sgl_log.h>
#include <sgl_cfgfix.h>
static tlsf_t mem_tlsf;
static sgl_mm_monitor_t mem = {
.total_size = 0,
.free_size = 0,
.used_size = 0,
};
/**
* @brief initialize memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_init(void *mem_start, size_t len)
{
mem_tlsf = tlsf_create_with_pool(mem_start, len);
mem.total_size += len;
}
/**
* @brief add memory pool
* @param mem_start start address of memory pool
* @param len length of memory pool
*/
void sgl_mm_add_pool(void *mem_start, size_t len)
{
tlsf_add_pool(mem_tlsf, mem_start, len);
mem.total_size += len;
}
/**
* @brief memory alloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
*
* @param size request size of memory
*
* @return point to request memory address
*/
void* sgl_malloc(size_t size)
{
void *ret = tlsf_malloc(mem_tlsf, size);
if(ret == NULL) {
SGL_LOG_ERROR("out of memory");
return NULL;
}
mem.used_size += size;
return ret;
}
/**
* @brief memory realloc, the function is unsafe, you should ensure that
* the requested size is smaller than the free size of memory
* @param p the pointer of request size of memory
* @param size request size of memory
*/
void* sgl_realloc(void *p, size_t size)
{
void *ret = tlsf_realloc(mem_tlsf, p, size);
if(ret == NULL) {
SGL_LOG_ERROR("out of memory");
return NULL;
}
mem.used_size += size;
return ret;
}
/**
* @brief memory free
*
* @param p the pointer of request size of memory
*
* @return none
*/
void sgl_free(void *p)
{
mem.used_size -= tlsf_block_size(p);
tlsf_free(mem_tlsf, p);
}
sgl_mm_monitor_t sgl_mm_get_monitor(void)
{
int integer = (mem.used_size * 100) / mem.total_size;
int decimal = (mem.used_size * 10000) / mem.total_size - (integer * 100);
mem.used_rate = integer << 8 | decimal;
mem.free_size = mem.total_size - mem.used_size;
return mem;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
#ifndef INCLUDED_tlsf
#define INCLUDED_tlsf
/*
** Two Level Segregated Fit memory allocator, version 3.1.
** Written by Matthew Conte
** http://tlsf.baisoku.org
**
** Based on the original documentation by Miguel Masmano:
** http://www.gii.upv.es/tlsf/main/docs
**
** This implementation was written to the specification
** of the document, therefore no GPL restrictions apply.
**
** Copyright (c) 2006-2016, Matthew Conte
** 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.
** * Neither the name of the copyright holder 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 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 MATTHEW CONTE 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 <stddef.h>
#include <sgl_cfgfix.h>
#if defined(__cplusplus)
extern "C" {
#endif
/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */
/* pool_t: a block of memory that TLSF can manage. */
typedef void* tlsf_t;
typedef void* pool_t;
/* Create/destroy a memory pool. */
tlsf_t tlsf_create(void* mem);
tlsf_t tlsf_create_with_pool(void* mem, size_t bytes);
void tlsf_destroy(tlsf_t tlsf);
pool_t tlsf_get_pool(tlsf_t tlsf);
/* Add/remove memory pools. */
pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes);
void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
/* malloc/memalign/realloc/free replacements. */
void* tlsf_malloc(tlsf_t tlsf, size_t bytes);
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t bytes);
void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size);
void tlsf_free(tlsf_t tlsf, void* ptr);
/* Returns internal block size, not original request size */
size_t tlsf_block_size(void* ptr);
/* Overheads/limits of internal structures. */
size_t tlsf_size(void);
size_t tlsf_align_size(void);
size_t tlsf_block_size_min(void);
size_t tlsf_block_size_max(void);
size_t tlsf_pool_overhead(void);
size_t tlsf_alloc_overhead(void);
/* Debugging. */
typedef void (*tlsf_walker)(void* ptr, size_t size, int used, void* user);
void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user);
/* Returns nonzero if any internal consistency check fails. */
int tlsf_check(tlsf_t tlsf);
int tlsf_check_pool(pool_t pool);
#if defined(__cplusplus)
};
#endif
#endif

65
User/system/sgl/sgl.h Normal file
View File

@ -0,0 +1,65 @@
/* source/sgl.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_H__
#define __SGL_H__
#include <sgl_list.h>
#include <sgl_core.h>
#include <sgl_anim.h>
#include <sgl_misc.h>
#include <sgl_types.h>
#include <sgl_font.h>
#include "widgets/line/sgl_line.h"
#include "widgets/rectangle/sgl_rectangle.h"
#include "widgets/circle/sgl_circle.h"
#include "widgets/ring/sgl_ring.h"
#include "widgets/arc/sgl_arc.h"
#include "widgets/button/sgl_button.h"
#include "widgets/slider/sgl_slider.h"
#include "widgets/progress/sgl_progress.h"
#include "widgets/label/sgl_label.h"
#include "widgets/switch/sgl_switch.h"
#include "widgets/msgbox/sgl_msgbox.h"
#include "widgets/textline/sgl_textline.h"
#include "widgets/textbox/sgl_textbox.h"
#include "widgets/checkbox/sgl_checkbox.h"
#include "widgets/icon/sgl_icon.h"
// #include "widgets/listview/sgl_listview.h"
#include "widgets/numberkbd/sgl_numberkbd.h"
#include "widgets/keyboard/sgl_keyboard.h"
#include "widgets/unzip_image/sgl_unzip_image.h"
#include "widgets/led/sgl_led.h"
#include "widgets/2dball/sgl_2dball.h"
#include "widgets/scroll/sgl_scroll.h"
#include "widgets/dropdown/sgl_dropdown.h"
#include "widgets/scope/sgl_scope.h"
#include "widgets/ext_img/sgl_ext_img.h"
#include "widgets/polygon/sgl_polygon.h"
#include "widgets/box/sgl_box.h"
#include "widgets/canvas/sgl_canvas.h"
#include "widgets/bar/sgl_bar.h"
#include "widgets/win/sgl_win.h"
#endif // __SGL_H__

View File

@ -0,0 +1,23 @@
//****************************************************************
//* lite-manager *
//* NOTE: do not edit this file as it is automatically generated *
//****************************************************************
#ifndef __CONFIG_H__
#define __CONFIG_H__
#define CONFIG_SGL_PANEL_PIXEL_DEPTH 16
#define CONFIG_SGL_EVENT_QUEUE_SIZE 16
#define CONFIG_SGL_ANIMATION 1
#define CONFIG_SGL_ANIMATION_TICK_MS 10
#define CONFIG_SGL_DEBUG 1
#define CONFIG_SGL_LOG_COLOR 1
#define CONFIG_SGL_LOG_LEVEL 0
#define CONFIG_SGL_BOOT_LOGO 1
#define CONFIG_SGL_HEAP_ALGO lwmem
#define CONFIG_SGL_HEAP_MEMORY_SIZE 10240
#define CONFIG_SGL_FONT_SONG23 1
#endif //!__CONFIG_H__

View File

@ -0,0 +1,122 @@
/* source/widgets/sgl_2dball.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_2dball.h"
static void sgl_2dball_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_2dball_t *ball = sgl_container_of(obj, sgl_2dball_t, obj);
int16_t cx = 0, cy = 0;
if(evt->type == SGL_EVENT_DRAW_MAIN) {
sgl_area_t clip;
sgl_color_t *buf = NULL, *blend = NULL;
cx = (ball->obj.coords.x1 + ball->obj.coords.x2) / 2;
cy = (ball->obj.coords.y1 + ball->obj.coords.y2) / 2;
if (!sgl_surf_clip(surf, &obj->area, &clip)) {
return;
}
sgl_area_t c_rect = {
.x1 = cx - obj->radius,
.x2 = cx + obj->radius,
.y1 = cy - obj->radius,
.y2 = cy + obj->radius
};
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
int y2 = 0, real_r2 = 0, edge_alpha = 0;
int r2 = sgl_pow2(obj->radius);
int r2_edge = sgl_pow2(obj->radius + 1);
int ds_alpha = SGL_ALPHA_MIN;
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
y2 = sgl_pow2(y - cy);
blend = buf;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
real_r2 = sgl_pow2(x - cx) + y2;
ds_alpha = real_r2 * SGL_ALPHA_NUM / r2;
if (real_r2 >= r2_edge) {
if(x > cx)
break;
continue;
}
else if (real_r2 >= r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
sgl_color_t color_mix = sgl_color_mixer(ball->bg_color, *blend, edge_alpha);
*blend = sgl_color_mixer(color_mix, *blend, ball->alpha);
}
else {
*blend = sgl_color_mixer(sgl_color_mixer(ball->bg_color, ball->color, ds_alpha), *blend, ball->alpha);
}
}
buf += surf->w;
}
}
}
/**
* @brief create a 2dball object
* @param parent parent of the 2dball
* @return 2dball object
*/
sgl_obj_t* sgl_2dball_create(sgl_obj_t* parent)
{
sgl_2dball_t *ball = sgl_malloc(sizeof(sgl_2dball_t));
if(ball == NULL) {
SGL_LOG_ERROR("sgl_2dball_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(ball, 0, sizeof(sgl_2dball_t));
sgl_obj_t *obj = &ball->obj;
sgl_obj_init(&ball->obj, parent);
obj->construct_fn = sgl_2dball_construct_cb;
obj->needinit = 1;
ball->alpha = SGL_ALPHA_MAX;
ball->color = SGL_THEME_COLOR;
ball->bg_color = SGL_THEME_BG_COLOR;
return obj;
}

View File

@ -0,0 +1,110 @@
/* source/widgets/sgl_2dball.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_2DBALL_H__
#define __SGL_2DBALL_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief sgl 2dball struct
* @obj: sgl general object
* @desc: pointer to 2dball draw descriptor
*/
typedef struct sgl_2dball {
sgl_obj_t obj;
uint8_t alpha;
sgl_color_t color;
sgl_color_t bg_color;
}sgl_2dball_t;
/**
* @brief create a 2dball object
* @param parent parent of the 2dball
* @return 2dball object
*/
sgl_obj_t* sgl_2dball_create(sgl_obj_t* parent);
/**
* @brief set the color of the 2dball
* @param obj 2dball object
* @param color color
* @return none
*/
static inline void sgl_2dball_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_2dball_t *ball = sgl_container_of(obj, sgl_2dball_t, obj);
ball->color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the background color of the 2dball
* @param obj 2dball object
* @param color background color
* @return none
*/
static inline void sgl_2dball_set_bg_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_2dball_t *ball = sgl_container_of(obj, sgl_2dball_t, obj);
ball->bg_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the alpha of the 2dball
* @param obj 2dball object
* @param alpha alpha
* @return none
*/
static inline void sgl_2dball_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_2dball_t *ball = sgl_container_of(obj, sgl_2dball_t, obj);
ball->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the radius of the 2dball
* @param obj 2dball object
* @param radius radius
* @return none
*/
static inline void sgl_2dball_set_radius(sgl_obj_t *obj, uint16_t radius)
{
sgl_obj_set_radius(obj, radius);
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_2DBALL_H__

View File

@ -0,0 +1,119 @@
/* source/widgets/sgl_arc.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_arc.h"
static void sgl_arc_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj);
int16_t tb_angle = 0;
if(evt->type == SGL_EVENT_DRAW_MAIN) {
arc->desc.cx = (obj->coords.x2 + obj->coords.x1) / 2;
arc->desc.cy = (obj->coords.y2 + obj->coords.y1) / 2;
if(arc->desc.start_angle == 0 && arc->desc.end_angle == 360) {
sgl_draw_fill_ring(surf, &arc->obj.area, arc->desc.cx, arc->desc.cy, arc->desc.radius_in, arc->desc.radius_out, arc->desc.color, arc->desc.alpha);
}
else {
sgl_draw_fill_arc(surf, &arc->obj.area, &arc->desc);
}
}
else if(evt->type == SGL_EVENT_PRESSED ||
evt->type == SGL_EVENT_MOVE_DOWN || evt->type == SGL_EVENT_MOVE_UP || evt->type == SGL_EVENT_MOVE_LEFT || evt->type == SGL_EVENT_MOVE_RIGHT
) {
tb_angle = sgl_atan2_angle(evt->pos.x - arc->desc.cx, evt->pos.y - arc->desc.cy);
tb_angle = 360 - tb_angle;
if ((tb_angle != arc->desc.end_angle) && tb_angle >= 0 && tb_angle <= 360) {
arc->desc.end_angle = tb_angle;
}
if(obj->event_fn) {
obj->event_fn(evt);
}
sgl_obj_set_dirty(obj);
}
else if(evt->type == SGL_EVENT_RELEASED) {
if(obj->event_fn) {
obj->event_fn(evt);
}
}
else if(SGL_EVENT_DRAW_INIT) {
if(arc->desc.radius_out < 0) {
arc->desc.radius_out = (obj->coords.x2 - obj->coords.x1) / 2;
}
if(arc->desc.radius_in < 0) {
arc->desc.radius_in = arc->desc.radius_out - 2;
}
}
}
/**
* @brief create an arc object
* @param parent parent object
* @return arc object
*/
sgl_obj_t* sgl_arc_create(sgl_obj_t* parent)
{
sgl_arc_t *arc = sgl_malloc(sizeof(sgl_arc_t));
if(arc == NULL) {
SGL_LOG_ERROR("sgl_arc_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(arc, 0, sizeof(sgl_arc_t));
sgl_obj_t *obj = &arc->obj;
sgl_obj_init(&arc->obj, parent);
obj->needinit = 1;
obj->clickable = 1;
obj->movable = 1;
arc->desc.alpha = SGL_THEME_ALPHA;
arc->desc.mode = SGL_ARC_MODE_NORMAL;
arc->desc.color = SGL_THEME_BG_COLOR;
arc->desc.bg_color = SGL_THEME_COLOR;
arc->desc.start_angle = 0;
arc->desc.end_angle = 360;
arc->desc.radius_out = -1;
arc->desc.radius_in = -1;
arc->desc.cx = -1;
arc->desc.cy = -1;
obj->construct_fn = sgl_arc_construct_cb;
return obj;
}

View File

@ -0,0 +1,149 @@
/* source/widgets/sgl_arc.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
#ifndef __SGL_ARC_H__
#define __SGL_ARC_H__
typedef struct sgl_arc {
sgl_obj_t obj;
sgl_draw_arc_t desc;
int16_t width;
}sgl_arc_t;
/**
* @brief create an arc object
* @param parent parent object
* @return arc object
*/
sgl_obj_t* sgl_arc_create(sgl_obj_t* parent);
/**
* @brief set arc object color
* @param obj arc object
* @param color arc color
* @return none
*/
static inline void sgl_arc_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj);
arc->desc.color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set arc object background color
* @param obj arc object
* @param color arc background color
* @return none
*/
static inline void sgl_arc_set_bg_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj);
arc->desc.bg_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set arc object alpha
* @param obj arc object
* @param alpha arc alpha
* @return none
*/
static inline void sgl_arc_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj);
arc->desc.alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set arc object radius
* @param obj arc object
* @param radius_in arc radius_in
* @param radius_out arc radius_out
* @return none
*/
static inline void sgl_arc_set_radius(sgl_obj_t *obj, int16_t radius_in, int16_t radius_out)
{
sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj);
sgl_obj_set_radius(obj, radius_out);
arc->desc.radius_in = radius_in;
arc->desc.radius_out = obj->radius;
sgl_obj_set_dirty(obj);
}
/**
* @brief set arc object mode
* @param obj arc object
* @param mode arc mode
* @return none
*/
static inline void sgl_arc_set_mode(sgl_obj_t *obj, uint8_t mode)
{
sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj);
arc->desc.mode = mode;
sgl_obj_set_dirty(obj);
}
/**
* @brief set arc object start angle
* @param obj arc object
* @param angle arc start angle
* @return none
* @note angle should be in range [0, 360]
*/
static inline void sgl_arc_set_start_angle(sgl_obj_t *obj, int16_t angle)
{
sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj);
arc->desc.start_angle = angle;
sgl_obj_set_dirty(obj);
}
/**
* @brief set arc object end angle
* @param obj arc object
* @param angle arc end angle
* @return none
* @note angle should be in range [0, 360]
*/
static inline void sgl_arc_set_end_angle(sgl_obj_t *obj, int16_t angle)
{
sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj);
arc->desc.end_angle = angle;
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_ARC_H__

View File

@ -0,0 +1,123 @@
/* source/widgets/sgl_bar.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_bar.h"
static void sgl_bar_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
sgl_draw_rect_t desc = {
.alpha = bar->alpha,
.border = obj->border,
.border_color = bar->border_color,
.pixmap = bar->pixmap,
.color = bar->track_color,
.radius = obj->radius,
};
sgl_area_t knob = {
.x1 = obj->coords.x1 + obj->border,
.x2 = obj->coords.x2 - obj->border,
.y1 = obj->coords.y1 + obj->border,
.y2 = obj->coords.y2 - obj->border,
};
if(evt->type == SGL_EVENT_DRAW_MAIN) {
if(bar->direct == SGL_DIRECT_HORIZONTAL) {
knob.x2 = obj->coords.x1 + (obj->coords.x2 - obj->coords.x1) * bar->value / 100 - obj->border;
}
else {
knob.y1 = obj->coords.y2 - (obj->coords.y2 - obj->coords.y1) * bar->value / 100 + obj->border;
}
/* set knob area */
sgl_area_selfclip(&knob, &obj->area);
sgl_draw_rect(surf, &obj->area, &obj->coords, &desc);
sgl_draw_fill_rect_with_border(surf, &knob, &obj->coords, obj->radius, bar->fill_color, bar->border_color, obj->border, bar->alpha);
}
else if(evt->type == SGL_EVENT_PRESSED ||
evt->type == SGL_EVENT_MOVE_DOWN || evt->type == SGL_EVENT_MOVE_UP || evt->type == SGL_EVENT_MOVE_LEFT || evt->type == SGL_EVENT_MOVE_RIGHT
) {
if(bar->direct == SGL_DIRECT_HORIZONTAL) {
bar->value = (evt->pos.x - obj->coords.x1) * 100 / (obj->coords.x2 - obj->coords.x1);
}
else {
bar->value = (obj->coords.y2 - evt->pos.y) * 100 / (obj->coords.y2 - obj->coords.y1);
}
if(evt->type == SGL_EVENT_PRESSED) {
sgl_obj_size_zoom(obj, 2);
}
sgl_obj_set_dirty(obj);
}
else if(evt->type == SGL_EVENT_RELEASED) {
sgl_obj_size_zoom(obj, -2);
sgl_obj_set_dirty(obj);
}
}
/**
* @brief create a bar object
* @param parent parent object of the bar
* @return bar object
*/
sgl_obj_t* sgl_bar_create(sgl_obj_t* parent)
{
sgl_bar_t *bar = sgl_malloc(sizeof(sgl_bar_t));
if(bar == NULL) {
SGL_LOG_ERROR("sgl_bar_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(bar, 0, sizeof(sgl_bar_t));
sgl_obj_t *obj = &bar->obj;
sgl_obj_init(&bar->obj, parent);
sgl_obj_set_clickable(obj);
sgl_obj_set_movable(obj);
obj->construct_fn = sgl_bar_construct_cb;
sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH);
bar->direct = SGL_DIRECT_HORIZONTAL;
bar->alpha = SGL_THEME_ALPHA;
bar->track_color = SGL_THEME_COLOR;
bar->border_color = SGL_THEME_BORDER_COLOR;
bar->fill_color = SGL_THEME_BG_COLOR;
bar->alpha = SGL_THEME_ALPHA;
return obj;
}

View File

@ -0,0 +1,204 @@
/* source/widgets/sgl_bar.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_BAR_H__
#define __SGL_BAR_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief sgl bar struct
* @obj: sgl general object
* @param track_color track color
* @param border_color border color
* @param pixmap pixmap
* @param fill_color fill color
* @param direct bar direction
* @param value bar value
* @param alpha alpha
*/
typedef struct sgl_bar {
sgl_obj_t obj;
sgl_color_t track_color;
sgl_color_t border_color;
const sgl_pixmap_t *pixmap;
sgl_color_t fill_color;
/* 0: horizontal, 1: vertical */
uint8_t direct : 1;
uint8_t value : 7;
uint8_t alpha;
} sgl_bar_t;
/**
* @brief create a bar object
* @param parent parent object of the bar
* @return bar object
*/
sgl_obj_t* sgl_bar_create(sgl_obj_t* parent);
/**
* @brief set the fill color of the bar
* @param obj bar object
* @param color fill color
* @return none
*/
static inline void sgl_bar_set_fill_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
bar->fill_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the fill alpha of the bar
* @param obj bar object
* @param alpha fill alpha
* @return none
*/
static inline void sgl_bar_set_fill_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
bar->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the track color of the bar
* @param obj bar object
* @param color track color
* @return none
*/
static inline void sgl_bar_set_track_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
bar->track_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the track alpha of the bar
* @param obj bar object
* @param alpha track alpha
* @return none
*/
static inline void sgl_bar_set_track_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
bar->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the bar direction
* @param obj bar object
* @param direct bar direction
* @return none
* @note direct : SGL_DIRECT_HORIZONTAL or SGL_DIRECT_VERTICAL
*/
static inline void sgl_bar_set_direct(sgl_obj_t *obj, uint8_t direct)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
bar->direct = direct;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the bar radius
* @param obj bar object
* @param radius bar radius
* @return none
*/
static inline void sgl_bar_set_radius(sgl_obj_t *obj, uint8_t radius)
{
sgl_obj_set_radius(obj, radius);
sgl_obj_set_dirty(obj);
}
/**
* @brief set the bar value
* @param obj bar object
* @param value bar value
* @return none
*/
static inline void sgl_bar_set_value(sgl_obj_t *obj, uint8_t value)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
bar->value = value;
sgl_obj_set_dirty(obj);
}
/**
* @brief get the bar value
* @param obj bar object
* @return bar value
*/
static inline uint8_t sgl_bar_get_value(sgl_obj_t *obj)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
return bar->value;
}
/**
* @brief set the bar border width
* @param obj bar object
* @param width border width
*/
static inline void sgl_bar_set_border_width(sgl_obj_t *obj, uint8_t width)
{
sgl_obj_set_border_width(obj, width);
sgl_obj_set_dirty(obj);
}
/**
* @brief set the bar border color
* @param obj bar object
* @param color border color
*/
static inline void sgl_bar_set_border_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
bar->border_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the bar pixmap
* @param obj bar object
* @param pixmap pixmap
*/
static inline void sgl_bar_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj);
bar->pixmap = pixmap;
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_BAR_H__

View File

@ -0,0 +1,265 @@
/* source/widgets/sgl_box.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: docs directory
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <sgl_theme.h>
#include "sgl_box.h"
#define SGL_BOX_SCROLL_WIDTH (4)
static void sgl_box_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
int16_t height = obj->coords.y2 - obj->coords.y1 - 2 * box->bg.radius;
int16_t width = obj->coords.x2 - obj->coords.x1 - 2 * box->bg.radius;
int16_t scroll_height = sgl_max(height / 8, SGL_BOX_SCROLL_WIDTH);
int16_t scroll_width = sgl_max(width / 8, SGL_BOX_SCROLL_WIDTH);
sgl_rect_t area;
if(evt->type == SGL_EVENT_DRAW_MAIN) {
area.x1 = obj->coords.x1 + box->bg.radius;
area.y1 = obj->coords.y1 + box->bg.radius;
area.x2 = obj->coords.x2 - box->bg.radius;
area.y2 = obj->coords.y2 - box->bg.radius;
sgl_draw_rect(surf, &obj->area, &obj->coords, &box->bg);
// Draw scrollbars if enabled
if(box->scroll_enable) {
// Draw vertical scrollbar if vertical scrolling is enabled and showing is enabled
if (((box->scroll_mode & SGL_BOX_SCROLL_VERTICAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH))
&& box->show_v_scrollbar) {
area.x1 = obj->coords.x2 - SGL_BOX_SCROLL_WIDTH - box->bg.radius;
area.y1 = obj->coords.y1 + box->bg.radius;
area.x2 = obj->coords.x2 - box->bg.radius;
// Calculate scroll bar position based on content size and current offset
// Use elastic_scroll values to determine content size for proper scrollbar positioning
int16_t content_height = height + (box->elastic_scroll_up + box->elastic_scroll_down);
if(content_height > height && content_height > 0) {
// Calculate the scroll bar's position based on the current y_offset
float scroll_ratio = (float)(-box->y_offset) / (content_height - height);
scroll_ratio = sgl_clamp(scroll_ratio, 0.0f, 1.0f); // Clamp between 0 and 1
int16_t max_scroll_pos = height - scroll_height;
area.y1 = obj->coords.y1 + box->bg.radius + (int16_t)(max_scroll_pos * scroll_ratio);
area.y2 = area.y1 + scroll_height;
} else {
// If content fits, position scrollbar at the top
area.y1 = obj->coords.y1 + box->bg.radius;
area.y2 = area.y1 + scroll_height;
}
sgl_draw_fill_rect(surf, &obj->area, &area, SGL_BOX_SCROLL_WIDTH / 2, box->scroll_color, 128);
}
// Draw horizontal scrollbar if horizontal scrolling is enabled and showing is enabled
if (((box->scroll_mode & SGL_BOX_SCROLL_HORIZONTAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH))
&& box->show_h_scrollbar) {
// Position horizontal scrollbar near the bottom-left, closer to vertical scrollbar
area.x1 = obj->coords.x1 + box->bg.radius;
area.y1 = obj->coords.y2 - SGL_BOX_SCROLL_WIDTH - box->bg.radius;
area.y2 = obj->coords.y2 - box->bg.radius;
// Adjust the right edge to not overlap with vertical scrollbar if both are visible
if ((box->scroll_mode & SGL_BOX_SCROLL_VERTICAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH)) {
area.x2 = obj->coords.x2 - SGL_BOX_SCROLL_WIDTH - box->bg.radius;
} else {
area.x2 = obj->coords.x2 - box->bg.radius;
}
// Calculate scroll bar position based on content size and current offset
int16_t content_width = width + (box->elastic_scroll_left + box->elastic_scroll_right);
if(content_width > width && content_width > 0) {
// Calculate the scroll bar's position based on the current x_offset
float scroll_ratio = (float)(-box->x_offset) / (content_width - width);
scroll_ratio = sgl_clamp(scroll_ratio, 0.0f, 1.0f); // Clamp between 0 and 1
int16_t max_scroll_pos = (area.x2 - area.x1) - scroll_width;
area.x1 = area.x1 + (int16_t)(max_scroll_pos * scroll_ratio);
area.x2 = area.x1 + scroll_width;
} else {
// If content fits, position scrollbar at the left
area.x1 = obj->coords.x1 + box->bg.radius;
area.x2 = area.x1 + scroll_width;
}
sgl_draw_fill_rect(surf, &obj->area, &area, SGL_BOX_SCROLL_WIDTH / 2, box->scroll_color, 128);
}
}
}
else if(evt->type == SGL_EVENT_MOVE_UP || evt->type == SGL_EVENT_MOVE_DOWN) {
// Check if vertical scrolling is enabled
if((box->scroll_mode & SGL_BOX_SCROLL_VERTICAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH)) {
// Update text offset - determine scroll direction based on event type
int16_t distance = evt->type == SGL_EVENT_MOVE_UP ? -evt->distance : evt->distance;
int16_t new_offset = box->y_offset + distance;
// Calculate limits based on elastic_scroll values
int16_t min_elastic, max_elastic;
// Calculate content dimensions based on elastic_scroll values
int16_t content_height = height + (box->elastic_scroll_up + box->elastic_scroll_down);
// Determine maximum scroll distance
int16_t max_scroll_distance = content_height - height;
if(box->elastic_scroll_up > 0 || box->elastic_scroll_down > 0) {
// If elastic scrolling is enabled (any direction limit > 0), limit to boundary plus elastic offset
// Apply actual elastic limits
min_elastic = -max_scroll_distance - box->elastic_scroll_down; // Allow scrolling down with elastic limit
max_elastic = box->elastic_scroll_up; // Allow scrolling up with elastic limit
} else {
// If elastic scrolling is disabled (both values are 0), limit to content boundaries
min_elastic = -max_scroll_distance; // max scroll down
max_elastic = 0; // max scroll up
}
int16_t constrained_new_offset = sgl_clamp(new_offset, min_elastic, max_elastic);
int16_t offset_delta = constrained_new_offset - box->y_offset;
box->y_offset = constrained_new_offset;
// Move all children vertically
sgl_obj_move_child_pos_y(obj, offset_delta);
sgl_obj_set_dirty(obj);
}
}
else if(evt->type == SGL_EVENT_MOVE_LEFT || evt->type == SGL_EVENT_MOVE_RIGHT) {
// Check if horizontal scrolling is enabled
if((box->scroll_mode & SGL_BOX_SCROLL_HORIZONTAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH)) {
// Update text offset - determine scroll direction based on event type
int16_t distance = evt->type == SGL_EVENT_MOVE_LEFT ? -evt->distance : evt->distance;
int16_t new_offset = box->x_offset + distance;
// Calculate limits based on elastic_scroll values
int16_t min_elastic, max_elastic;
// Calculate content dimensions based on elastic_scroll values
int16_t content_width = width + (box->elastic_scroll_left + box->elastic_scroll_right);
// Determine maximum scroll distance
int16_t max_scroll_distance = content_width - width;
if(box->elastic_scroll_left > 0 || box->elastic_scroll_right > 0) {
// If elastic scrolling is enabled (any direction limit > 0), limit to boundary plus elastic offset
// Apply actual elastic limits
min_elastic = -max_scroll_distance - box->elastic_scroll_right; // Allow scrolling right with elastic limit
max_elastic = box->elastic_scroll_left; // Allow scrolling left with elastic limit
} else {
// If elastic scrolling is disabled (both values are 0), limit to content boundaries
min_elastic = -max_scroll_distance; // max scroll right
max_elastic = 0; // max scroll left
}
int16_t constrained_new_offset = sgl_clamp(new_offset, min_elastic, max_elastic);
int16_t offset_delta = constrained_new_offset - box->x_offset;
box->x_offset = constrained_new_offset;
// Move all children horizontally
sgl_obj_move_child_pos_x(obj, offset_delta);
sgl_obj_set_dirty(obj);
}
}
else if (evt->type == SGL_EVENT_PRESSED) {
box->scroll_enable = 1;
sgl_obj_set_dirty(obj);
}
else if (evt->type == SGL_EVENT_RELEASED) {
box->scroll_enable = 0;
sgl_obj_set_dirty(obj);
}
}
/**
* @brief create a box object
* @param parent parent of the box
* @return pointer to the box object
*/
sgl_obj_t* sgl_box_create(sgl_obj_t* parent)
{
sgl_box_t *box = sgl_malloc(sizeof(sgl_box_t));
if(box == NULL) {
SGL_LOG_ERROR("sgl_box_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(box, 0, sizeof(sgl_box_t));
sgl_obj_t *obj = &box->obj;
sgl_obj_init(&box->obj, parent);
obj->construct_fn = sgl_box_construct_cb;
sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH);
obj->focus = 1;
sgl_obj_set_clickable(obj);
sgl_obj_set_movable(obj);
box->bg.alpha = SGL_THEME_ALPHA;
box->bg.color = SGL_THEME_COLOR;
box->bg.radius = 10;
box->bg.border = 1;
sgl_obj_set_border_width(obj, 1);
box->bg.border_color = SGL_THEME_BORDER_COLOR;
box->scroll_color = SGL_THEME_SCROLL_FG_COLOR;
box->x_offset = 0;
box->y_offset = 0;
box->scroll_enable = 0;
box->show_v_scrollbar = 1;
box->show_h_scrollbar = 1;
box->scroll_mode = SGL_BOX_SCROLL_BOTH;
box->elastic_scroll_up = 0; // Default: unlimited scrolling up
box->elastic_scroll_down = 0; // Default: unlimited scrolling down
box->elastic_scroll_left = 0; // Default: unlimited scrolling left
box->elastic_scroll_right = 0; // Default: unlimited scrolling right
return obj;
}
/**
* @brief Set the elastic scroll limits for up and down directions
* @param obj box object
* @param up_limit maximum pixels allowed when scrolling up (0 for unlimited)
* @param down_limit maximum pixels allowed when scrolling down (0 for unlimited)
* @param left_limit maximum pixels allowed when scrolling left (0 for unlimited)
* @param right_limit maximum pixels allowed when scrolling right (0 for unlimited)
* @return none
*/
void sgl_box_set_elastic_scroll(sgl_obj_t* obj, int16_t up_limit, int16_t down_limit, int16_t left_limit, int16_t right_limit)
{
SGL_ASSERT(obj != NULL);
sgl_box_t *box = (sgl_box_t*)obj;
box->elastic_scroll_up = up_limit;
box->elastic_scroll_down = down_limit;
box->elastic_scroll_left = left_limit;
box->elastic_scroll_right = right_limit;
}

View File

@ -0,0 +1,189 @@
/* source/widgets/sgl_box.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: docs directory
*
* 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.
*/
#ifndef __SGL_BOX_H__
#define __SGL_BOX_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
// Define scroll modes
#define SGL_BOX_SCROLL_VERTICAL_ONLY (0x01) // Vertical scrolling only
#define SGL_BOX_SCROLL_HORIZONTAL_ONLY (0x02) // Horizontal scrolling only
#define SGL_BOX_SCROLL_BOTH (0x03) // Both vertical and horizontal scrolling enabled
/**
* @brief sgl box struct
* @desc: Container for scrolling child widgets
*/
typedef struct sgl_box {
sgl_obj_t obj;
sgl_draw_rect_t bg;
int16_t x_offset; // X-axis offset
int16_t y_offset; // Y-axis offset
sgl_color_t scroll_color; // scroll color;
uint8_t scroll_mode; // Scroll mode (vertical/horizontal/both)
uint8_t scroll_enable : 1; // Whether scrolling is enabled
uint8_t show_v_scrollbar : 1; // Whether to show the vertical scrollbar
uint8_t show_h_scrollbar : 1; // Whether to show the horizontal scrollbar
int16_t elastic_scroll_up; // Maximum allowable upward elastic scroll offset
int16_t elastic_scroll_down; // Maximum allowable downward elastic scroll offset
int16_t elastic_scroll_left; // Maximum allowable leftward elastic scroll offset
int16_t elastic_scroll_right; // Maximum allowable rightward elastic scroll offset
} sgl_box_t;
/**
* @brief create a box object
* @param parent parent of the box
* @return box object
*/
sgl_obj_t* sgl_box_create(sgl_obj_t* parent);
/**
* @brief set background color of the box
* @param obj box object
* @param color background color to be set
* @return none
*/
static inline void sgl_box_set_bg_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
box->bg.color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set radius of the box
* @param obj box object
* @param radius radius to be set
* @return none
*/
static inline void sgl_box_set_radius(sgl_obj_t *obj, uint8_t radius)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
sgl_obj_set_radius(obj, radius);
box->bg.radius = obj->radius;
sgl_obj_set_dirty(obj);
}
/**
* @brief set border color of the box
* @param obj box object
* @param color border color to be set
* @return none
*/
static inline void sgl_box_set_border_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
box->bg.border_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set border width of the box
* @param obj box object
* @param width border width to be set
* @return none
*/
static inline void sgl_box_set_border_width(sgl_obj_t *obj, uint8_t width)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
box->bg.border = width;
sgl_obj_set_border_width(obj, width);
sgl_obj_set_dirty(obj);
}
/**
* @brief set box pixmap
* @param obj box object
* @param pixmap pixmap to be set
* @return none
*/
static inline void sgl_box_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
box->bg.pixmap = pixmap;
sgl_obj_set_dirty(obj);
}
/**
* @brief Set the elastic scroll limits for up and down directions
* @param obj box object
* @param up_limit maximum pixels allowed when scrolling up (0 for unlimited)
* @param down_limit maximum pixels allowed when scrolling down (0 for unlimited)
* @param left_limit maximum pixels allowed when scrolling left (0 for unlimited)
* @param right_limit maximum pixels allowed when scrolling right (0 for unlimited)
* @return none
*/
void sgl_box_set_elastic_scroll(sgl_obj_t* obj, int16_t up_limit, int16_t down_limit, int16_t left_limit, int16_t right_limit);
/**
* @brief set scrollbar color of the box
* @param obj box object
* @param color scrollbar color to be set
* @return none
*/
static inline void sgl_box_set_scrollbar_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
box->scroll_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set whether to show scrollbars
* @param obj box object
* @param show_vertical whether to show vertical scrollbar (1 to show, 0 to hide)
* @param show_horizontal whether to show horizontal scrollbar (1 to show, 0 to hide)
* @return none
*/
static inline void sgl_box_set_show_scrollbar(sgl_obj_t *obj, uint8_t show_vertical, uint8_t show_horizontal)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
box->show_v_scrollbar = show_vertical;
box->show_h_scrollbar = show_horizontal;
sgl_obj_set_dirty(obj);
}
/**
* @brief set alpha (transparency) of the box
* @param obj box object
* @param alpha alpha value to be set (0-255, where 0 is fully transparent and 255 is fully opaque)
* @return none
*/
static inline void sgl_box_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj);
box->bg.alpha = alpha;
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_BOX_H__

View File

@ -0,0 +1,54 @@
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
set(SGL_SOURCE
${SGL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/line/sgl_line.c
${CMAKE_CURRENT_LIST_DIR}/rectangle/sgl_rectangle.c
${CMAKE_CURRENT_LIST_DIR}/circle/sgl_circle.c
${CMAKE_CURRENT_LIST_DIR}/ring/sgl_ring.c
${CMAKE_CURRENT_LIST_DIR}/arc/sgl_arc.c
${CMAKE_CURRENT_LIST_DIR}/button/sgl_button.c
${CMAKE_CURRENT_LIST_DIR}/slider/sgl_slider.c
${CMAKE_CURRENT_LIST_DIR}/progress/sgl_progress.c
${CMAKE_CURRENT_LIST_DIR}/label/sgl_label.c
${CMAKE_CURRENT_LIST_DIR}/switch/sgl_switch.c
${CMAKE_CURRENT_LIST_DIR}/msgbox/sgl_msgbox.c
${CMAKE_CURRENT_LIST_DIR}/textline/sgl_textline.c
${CMAKE_CURRENT_LIST_DIR}/textbox/sgl_textbox.c
${CMAKE_CURRENT_LIST_DIR}/checkbox/sgl_checkbox.c
${CMAKE_CURRENT_LIST_DIR}/icon/sgl_icon.c
${CMAKE_CURRENT_LIST_DIR}/numberkbd/sgl_numberkbd.c
${CMAKE_CURRENT_LIST_DIR}/keyboard/sgl_keyboard.c
${CMAKE_CURRENT_LIST_DIR}/led/sgl_led.c
${CMAKE_CURRENT_LIST_DIR}/2dball/sgl_2dball.c
${CMAKE_CURRENT_LIST_DIR}/unzip_image/sgl_unzip_image.c
${CMAKE_CURRENT_LIST_DIR}/scroll/sgl_scroll.c
${CMAKE_CURRENT_LIST_DIR}/dropdown/sgl_dropdown.c
${CMAKE_CURRENT_LIST_DIR}/scope/sgl_scope.c
${CMAKE_CURRENT_LIST_DIR}/polygon/sgl_polygon.c
${CMAKE_CURRENT_LIST_DIR}/box/sgl_box.c
${CMAKE_CURRENT_LIST_DIR}/canvas/sgl_canvas.c
${CMAKE_CURRENT_LIST_DIR}/bar/sgl_bar.c
${CMAKE_CURRENT_LIST_DIR}/win/sgl_win.c
)

View File

@ -0,0 +1,121 @@
/* source/widgets/sgl_button.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <sgl_theme.h>
#include <string.h>
#include "sgl_button.h"
/**
* @brief button construct callback
* @param surf: surface pointer
* @param obj: object pointer
* @param evt: event pointer
* @return none
* @note this function is called when the object is created or redraw
*/
static void sgl_button_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
sgl_pos_t align_pos;
sgl_rect_t fill_area;
sgl_draw_rect_t rect = {
.alpha = button->alpha,
.color = button->color,
.border = obj->border,
.border_color = button->border_color,
.pixmap = button->pixmap,
.radius = obj->radius,
};
if(evt->type == SGL_EVENT_DRAW_MAIN) {
sgl_draw_rect(surf, &obj->area, &obj->coords, &rect);
if(button->text) {
SGL_ASSERT(button->font != NULL);
fill_area = sgl_obj_get_fill_rect(obj);
align_pos = sgl_get_text_pos(&fill_area, button->font, button->text, 0, (sgl_align_type_t)button->align);
sgl_draw_string(surf, &obj->area, align_pos.x, align_pos.y, button->text, button->text_color, button->alpha, button->font);
}
}
else if(evt->type == SGL_EVENT_PRESSED) {
if(sgl_obj_is_flexible(obj)) {
sgl_obj_size_zoom(obj, 2);
}
sgl_obj_set_dirty(obj);
}
else if(evt->type == SGL_EVENT_RELEASED) {
if(sgl_obj_is_flexible(obj)) {
sgl_obj_size_zoom(obj, -2);
}
sgl_obj_set_dirty(obj);
}
}
/**
* @brief create a button object
* @param parent: parent object
* @return object pointer
* @note if parent is NULL, the button object will be created at the top level.
*/
sgl_obj_t* sgl_button_create(sgl_obj_t* parent)
{
sgl_button_t *button = sgl_malloc(sizeof(sgl_button_t));
if(button == NULL) {
SGL_LOG_ERROR("sgl_button_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(button, 0, sizeof(sgl_button_t));
sgl_obj_t *obj = &button->obj;
sgl_obj_init(&button->obj, parent);
sgl_obj_set_clickable(obj);
sgl_obj_set_flexible(obj);
sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH);
sgl_obj_set_radius(obj, SGL_THEME_RADIUS);
obj->construct_fn = sgl_button_construct_cb;
button->alpha = SGL_THEME_ALPHA;
button->color = SGL_THEME_COLOR;
button->border_color = SGL_THEME_BORDER_COLOR;
button->pixmap = NULL;
button->text = " ";
button->text_color = SGL_THEME_TEXT_COLOR;
button->font = sgl_get_system_font();
button->align = SGL_ALIGN_CENTER;
return obj;
}

View File

@ -0,0 +1,193 @@
/* source/widgets/sgl_button.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_BUTTON_H__
#define __SGL_BUTTON_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief Button object
* @obj: Button object
* @desc: Button object description
* @desc_text: Button object description text
*/
typedef struct sgl_button {
sgl_obj_t obj;
sgl_color_t color;
sgl_color_t border_color;
const sgl_pixmap_t *pixmap;
const char *text;
const sgl_font_t *font;
sgl_color_t text_color;
uint8_t alpha;
uint8_t align;
}sgl_button_t;
/**
* @brief create a button object
* @param parent: parent object
* @return object pointer
* @note if parent is NULL, the button object will be created at the top level.
*/
sgl_obj_t* sgl_button_create(sgl_obj_t* parent);
/**
* @brief set button color
* @param obj: object pointer
* @param color: color
* @return none
*/
static inline void sgl_button_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
button->color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set button alpha
* @param obj: object pointer
* @param alpha: alpha
* @return none
*/
static inline void sgl_button_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
button->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set button border width
* @param obj: object pointer
* @param width: border width
* @return none
*/
static inline void sgl_button_set_border_width(sgl_obj_t *obj, uint8_t width)
{
sgl_obj_set_border_width(obj, width);
sgl_obj_set_dirty(obj);
}
/**
* @brief set button border color
* @param obj: object pointer
* @param color: border color
* @return none
*/
static inline void sgl_button_set_border_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
button->border_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set button pixmap
* @param obj: object pointer
* @param pixmap: pixmap pointer
* @return none
*/
static inline void sgl_button_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
button->pixmap = pixmap;
sgl_obj_set_dirty(obj);
}
/**
* @brief set button radius
* @param obj: object pointer
* @param radius: radius
* @return none
*/
static inline void sgl_button_set_radius(sgl_obj_t *obj, uint8_t radius)
{
sgl_obj_set_radius(obj, radius);
sgl_obj_set_dirty(obj);
}
/**
* @brief set button text
* @param obj: object pointer
* @param text: text
* @return none
*/
static inline void sgl_button_set_text(sgl_obj_t *obj, const char *text)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
button->text = text;
sgl_obj_set_dirty(obj);
}
/**
* @brief set button text color
* @param obj: object pointer
* @param color: text color
* @return none
*/
static inline void sgl_button_set_text_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
button->text_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set button text align
* @param obj: object pointer
* @param align: align type
* @return none
*/
static inline void sgl_button_set_text_align(sgl_obj_t *obj, uint8_t align)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
button->align = align;
sgl_obj_set_dirty(obj);
}
/**
* @brief set button text font
* @param obj: object pointer
* @param font: font pointer
* @return none
*/
static inline void sgl_button_set_font(sgl_obj_t *obj, const sgl_font_t *font)
{
sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj);
button->font = font;
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_BUTTON_H__

View File

@ -0,0 +1,67 @@
/* source/widgets/sgl_canvas.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: docs directory
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_canvas.h"
static void sgl_canvas_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_canvas_t *canvas = sgl_container_of(obj, sgl_canvas_t, obj);
if(evt->type == SGL_EVENT_DRAW_MAIN) {
SGL_ASSERT_INFO(canvas->painter != NULL, "you must set painter function");
canvas->painter(surf, &obj->area, obj);
}
}
/**
* @brief create a canvas object
* @param parent parent of the canvas
* @return canvas object
*/
sgl_obj_t* sgl_canvas_create(sgl_obj_t* parent)
{
sgl_canvas_t *canvas = sgl_malloc(sizeof(sgl_canvas_t));
if(canvas == NULL) {
SGL_LOG_ERROR("sgl_canvas_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(canvas, 0, sizeof(sgl_canvas_t));
sgl_obj_t *obj = &canvas->obj;
sgl_obj_init(&canvas->obj, parent);
obj->construct_fn = sgl_canvas_construct_cb;
return obj;
}

View File

@ -0,0 +1,97 @@
/* source/widgets/sgl_canvas.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: docs directory
*
* 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.
*/
#ifndef __SGL_CANVAS_H__
#define __SGL_CANVAS_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief For example, you can use the canvas widget:
* void painter_func(sgl_surf_t *surf, sgl_area_t *area, sgl_obj_t *obj)
* {
* for (int i = obj->coords.y1; i < obj->coords.y2; i += 10) {
* sgl_draw_fill_hline(surf, area, i, obj->coords.x1, obj->coords.x2, 5, SGL_COLOR_BLACK, 255);
* }
* }
*
* sgl_obj_t *canvas = sgl_canvas_create(NULL);
* sgl_obj_set_size(canvas, 800, 600);
* sgl_obj_set_pos_align(canvas, SGL_ALIGN_CENTER);
* sgl_canvas_set_painter_cb(canvas, painter_func);
*/
typedef void (*sgl_painter_cb_t)(sgl_surf_t *surf, sgl_area_t *area, sgl_obj_t* obj);
/**
* @brief sgl canvas struct
* @obj: sgl general object
* @painter: pointer to canvas painter function
* @priv: pointer to canvas private data
*/
typedef struct sgl_canvas {
sgl_obj_t obj;
sgl_painter_cb_t painter;
void *priv;
} sgl_canvas_t;
/**
* @brief create a canvas object
* @param parent parent of the canvas
* @return canvas object
*/
sgl_obj_t* sgl_canvas_create(sgl_obj_t* parent);
/**
* @brief set canvas painter
* @param obj canvas object
* @param painter painter function
*/
static inline void sgl_canvas_set_painter_cb(sgl_obj_t *obj, sgl_painter_cb_t painter)
{
SGL_ASSERT(obj != NULL);
sgl_canvas_t *canvas = sgl_container_of(obj, sgl_canvas_t, obj);
canvas->painter = painter;
}
/**
* @brief set canvas private data
* @param obj canvas object
* @param priv private data
* @param none
*/
static inline void sgl_canvas_set_private(sgl_obj_t *obj, void *priv)
{
SGL_ASSERT(obj != NULL);
sgl_canvas_t *canvas = (sgl_canvas_t *)obj;
canvas->priv = priv;
}
#endif // !__SGL_CANVAS_H__

View File

@ -0,0 +1,190 @@
/* source/widgets/sgl_checkbox.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_checkbox.h"
static const uint8_t unchecked_pixmap[] = {
/*  */
0x00,0x03,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00,
0x05,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xea,0x00,0x00,0x00,
0x8e,0xfe,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xce,0xff,0xa0,0x00,0x00,
0xef,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0xe0,0x00,0x00,
0xef,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xcf,0xe0,0x00,0x00,
0x5e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x80,0x00,0x00,
0x03,0xcf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc5,0x00,0x00,0x00,
};
static const uint8_t checked_pixmap[] = {
/*  */
0x00,0x03,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00,
0x05,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0x00,0x30,0x00,
0x8e,0xfe,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x80,0x5e,0xfa,0x00,
0xef,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xef,0xff,0xa0,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xff,0xff,0xe0,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xef,0xff,0xff,0xe0,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xff,0xff,0xfe,0x30,
0xee,0x50,0x03,0x55,0x00,0x00,0x00,0x05,0xef,0xff,0xff,0xe3,0x00,
0xee,0x50,0x3e,0xfe,0x80,0x00,0x00,0x5e,0xff,0xff,0xfe,0x30,0x00,
0xee,0x50,0xef,0xff,0xe8,0x00,0x05,0xef,0xff,0xff,0xe3,0x00,0x00,
0xee,0x58,0xef,0xff,0xfe,0x80,0x5e,0xff,0xff,0xfe,0x30,0x00,0x00,
0xee,0x50,0xcf,0xff,0xff,0xe8,0xef,0xff,0xff,0xe3,0x00,0x00,0x00,
0xee,0x50,0x0c,0xff,0xff,0xff,0xff,0xff,0xfe,0x30,0x85,0x00,0x00,
0xee,0x50,0x00,0xcf,0xff,0xff,0xff,0xff,0xe3,0x0c,0xe8,0x00,0x00,
0xee,0x50,0x00,0x0c,0xff,0xff,0xff,0xfe,0x30,0x0e,0xe8,0x00,0x00,
0xee,0x50,0x00,0x00,0xcf,0xff,0xff,0xe3,0x00,0x0e,0xe8,0x00,0x00,
0xee,0x50,0x00,0x00,0x0c,0xff,0xfe,0x30,0x00,0x0e,0xe8,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0xcf,0xe3,0x00,0x00,0x0e,0xe8,0x00,0x00,
0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0xe8,0x00,0x00,
0xef,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xcf,0xe3,0x00,0x00,
0x5e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x80,0x00,0x00,
0x03,0xcf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc5,0x00,0x00,0x00,
};
static sgl_icon_pixmap_t unchecked_icon = {
.bitmap = unchecked_pixmap,
.height = 22,
.width = 26,
};
static sgl_icon_pixmap_t checked_icon = {
.bitmap = checked_pixmap,
.height = 22,
.width = 26,
};
/**
* @brief checkbox construct callback
* @param surf surface pointer
* @param obj checkbox object
* @param evt event parameter
* @return none
*/
static void sgl_checkbox_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj);
int text_x = 0, icon_y = 0;
sgl_pos_t align_pos;
SGL_ASSERT(checkbox->font != NULL);
if(evt->type == SGL_EVENT_DRAW_MAIN) {
if(checkbox->status) {
checkbox->icon = &checked_icon;
}
else {
checkbox->icon = &unchecked_icon;
}
if (checkbox->icon) {
text_x = checkbox->icon->width + 2;
}
align_pos = sgl_get_text_pos(&obj->coords, checkbox->font, checkbox->text, text_x, SGL_ALIGN_CENTER);
if (checkbox->icon) {
icon_y = ((obj->coords.y2 - obj->coords.y1) - (checkbox->icon->height)) / 2 + 1;
sgl_draw_icon(surf, &obj->area, align_pos.x, obj->coords.y1 + icon_y, checkbox->color, checkbox->alpha, checkbox->icon);
}
sgl_draw_string(surf, &obj->area, align_pos.x + text_x, align_pos.y, checkbox->text, checkbox->color, checkbox->alpha, checkbox->font);
}
else if(evt->type == SGL_EVENT_PRESSED) {
checkbox->status = !checkbox->status;
sgl_obj_set_dirty(obj);
}
else if(evt->type == SGL_EVENT_DRAW_INIT) {
if(obj->coords.y2 < obj->coords.y1) {
obj->coords.y2 = obj->coords.y1 + unchecked_icon.height;
}
if(obj->coords.x2 < obj->coords.x1) {
obj->coords.x2 = obj->coords.x1 + (checked_icon.width + sgl_font_get_string_width(checkbox->text, checkbox->font));
}
}
}
/**
* @brief create a checkbox object
* @param parent parent of the checkbox
* @return checkbox object
*/
sgl_obj_t* sgl_checkbox_create(sgl_obj_t* parent)
{
sgl_checkbox_t *checkbox = sgl_malloc(sizeof(sgl_checkbox_t));
if(checkbox == NULL) {
SGL_LOG_ERROR("sgl_checkbox_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(checkbox, 0, sizeof(sgl_checkbox_t));
sgl_obj_t *obj = &checkbox->obj;
sgl_obj_init(&checkbox->obj, parent);
obj->construct_fn = sgl_checkbox_construct_cb;
obj->needinit = 1;
checkbox->status = false;
checkbox->alpha = SGL_ALPHA_MAX;
checkbox->color = SGL_THEME_TEXT_COLOR;
checkbox->icon = &unchecked_icon;
obj->coords.y2 = SGL_POS_INVALID;
obj->coords.x2 = SGL_POS_INVALID;
sgl_obj_set_clickable(obj);
checkbox->font = sgl_get_system_font();
checkbox->text = " ";
return obj;
}

View File

@ -0,0 +1,132 @@
/* source/widgets/sgl_checkbox.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_CHECKBOX_H__
#define __SGL_CHECKBOX_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
typedef struct sgl_checkbox {
sgl_obj_t obj;
const char *text;
const sgl_font_t *font;
const sgl_icon_pixmap_t *icon;
sgl_color_t color;
uint8_t alpha;
bool status;
} sgl_checkbox_t;
/**
* @brief create a checkbox object
* @param parent parent of the checkbox
* @return checkbox object
*/
sgl_obj_t* sgl_checkbox_create(sgl_obj_t* parent);
/**
* @brief set checkbox text and icon color
* @param obj checkbox object
* @param color color of text
* @return none
*/
static inline void sgl_checkbox_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj);
checkbox->color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set checkbox text and icon alpha
* @param obj checkbox object
* @param alpha alpha of text
* @return none
*/
static inline void sgl_checkbox_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj);
checkbox->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set checkbox text
* @param obj checkbox object
* @param text text of checkbox
* @return none
*/
static inline void sgl_checkbox_set_text(sgl_obj_t *obj, const char *text)
{
sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj);
checkbox->text = text;
sgl_obj_set_dirty(obj);
}
/**
* @brief set checkbox font
* @param obj checkbox object
* @param font font of checkbox
* @return none
*/
static inline void sgl_checkbox_set_font(sgl_obj_t *obj, const sgl_font_t *font)
{
sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj);
checkbox->font = font;
sgl_obj_set_dirty(obj);
}
/**
* @brief set checkbox status
* @param obj checkbox object
* @param status status of checkbox
* @return none
*/
static inline void sgl_checkbox_set_status(sgl_obj_t *obj, bool status)
{
sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj);
checkbox->status = status;
sgl_obj_set_dirty(obj);
}
/**
* @brief get checkbox status
* @param obj checkbox object
* @return status of checkbox
*/
static inline bool sgl_checkbox_get_status(sgl_obj_t *obj)
{
sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj);
return checkbox->status;
}
#endif // !__SGL_CHECKBOX_H__

View File

@ -0,0 +1,94 @@
/* source/widgets/sgl_circle.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_circle.h"
/**
* @brief construct function of the circle object
* @param surf pointer to the surface
* @param obj pointer to the object
* @param evt pointer to the event
* @return none
*/
static void sgl_circle_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj);
if(evt->type == SGL_EVENT_DRAW_MAIN) {
circle->desc.cx = (circle->obj.coords.x1 + circle->obj.coords.x2) / 2;
circle->desc.cy = (circle->obj.coords.y1 + circle->obj.coords.y2) / 2;
sgl_draw_circle(surf, &obj->area, &circle->desc);
}
else if(evt->type == SGL_EVENT_DRAW_INIT) {
if(circle->desc.radius == -1) {
circle->desc.radius = (circle->obj.coords.y2 - circle->obj.coords.y1) / 2;
}
}
}
/**
* @brief create a circle object
* @param parent parent of the object
* @return pointer to the object
*/
sgl_obj_t* sgl_circle_create(sgl_obj_t* parent)
{
sgl_circle_t *circle = sgl_malloc(sizeof(sgl_circle_t));
if(circle == NULL) {
SGL_LOG_ERROR("sgl_circle_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(circle, 0, sizeof(sgl_circle_t));
sgl_obj_t *obj = &circle->obj;
sgl_obj_init(&circle->obj, parent);
obj->construct_fn = sgl_circle_construct_cb;
sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH);
obj->needinit = 1;
circle->desc.alpha = SGL_ALPHA_MAX;
circle->desc.color = SGL_THEME_COLOR;
circle->desc.pixmap = NULL;
circle->desc.border = SGL_THEME_BORDER_WIDTH;
circle->desc.border_color = SGL_THEME_BORDER_COLOR;
circle->desc.cx = -1;
circle->desc.cy = -1;
circle->desc.radius = -1;
return obj;
}

View File

@ -0,0 +1,138 @@
/* source/widgets/sgl_circle.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_CIRCLE_H__
#define __SGL_CIRCLE_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief draw a circle
* @obj: sgl general object
* @desc: circle description
*/
typedef struct sgl_circle {
sgl_obj_t obj;
sgl_draw_circle_t desc;
}sgl_circle_t;
/**
* @brief create a circle object
* @param parent parent of the object
* @return pointer to the object
*/
sgl_obj_t* sgl_circle_create(sgl_obj_t* parent);
/**
* @brief set the color of the circle
* @param obj pointer to the object
* @param color color of the circle
* @return none
*/
static inline void sgl_circle_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj);
circle->desc.color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the radius of the circle
* @param obj pointer to the object
* @param radius radius of the circle
* @return none
*/
static inline void sgl_circle_set_radius(sgl_obj_t *obj, uint16_t radius)
{
sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj);
sgl_obj_set_radius(obj, radius);
circle->desc.radius = obj->radius;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the alpha of the circle
* @param obj pointer to the object
* @param alpha alpha of the circle
* @return none
*/
static inline void sgl_circle_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj);
circle->desc.alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the pixmap of the circle
* @param obj pointer to the object
* @param pixmap pixmap of the circle
* @return none
*/
static inline void sgl_circle_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj);
circle->desc.pixmap = pixmap;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the border color of the circle
* @param obj pointer to the object
* @param color border color of the circle
* @return none
*/
static inline void sgl_circle_set_border_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj);
circle->desc.border_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the border width of the circle
* @param obj pointer to the object
* @param width border width of the circle
* @return none
*/
static inline void sgl_circle_set_border_width(sgl_obj_t *obj, uint8_t width)
{
sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj);
circle->desc.border = width;
sgl_obj_set_border_width(obj, width);
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_CIRCLE_H__

View File

@ -0,0 +1,329 @@
/* source/widgets/sgl_dropdown.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <sgl_theme.h>
#include "sgl_dropdown.h"
static const uint8_t dropdown_bitmap[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,
0x0c,0xfa,0x00,0x00,0x00,0x00,0x05,0xee,0x50,
0x0c,0xff,0xa0,0x00,0x00,0x00,0x5e,0xfe,0x30,
0x00,0xcf,0xfa,0x00,0x00,0x05,0xef,0xe3,0x00,
0x00,0x0c,0xff,0xa0,0x00,0x5e,0xfe,0x30,0x00,
0x00,0x00,0xcf,0xfa,0x05,0xef,0xe3,0x00,0x00,
0x00,0x00,0x0c,0xff,0xae,0xfe,0x30,0x00,0x00,
0x00,0x00,0x00,0xcf,0xff,0xe3,0x00,0x00,0x00,
0x00,0x00,0x00,0x0c,0xfe,0x30,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x00,
};
static const sgl_icon_pixmap_t dropdown_icon = {
.bitmap = dropdown_bitmap,
.height = 10,
.width = 18,
};
static void sgl_dropdown_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
int16_t icon_h = dropdown->option_h;
int16_t pos_x = 0, pos_y = 0, icon_y = 0;
sgl_dropdown_option_t *option = dropdown->head;
sgl_rect_t body_area = {
.x1 = obj->coords.x1,
.x2 = obj->coords.x2,
.y1 = obj->coords.y1,
.y2 = obj->coords.y1 + dropdown->option_h,
};
sgl_rect_t icon_area = {
.x1 = obj->coords.x2 - dropdown_icon.width - dropdown->body_desc.radius,
.x2 = obj->coords.x2 - 2,
.y1 = obj->coords.y1,
.y2 = obj->coords.y2,
};
sgl_rect_t text_area = {
.x1 = obj->coords.x1 + 2,
.x2 = obj->coords.x2 - dropdown_icon.width - 5,
.y1 = obj->coords.y1,
.y2 = obj->coords.y2,
};
icon_y = obj->coords.y1 + (icon_h - dropdown_icon.height) / 2;
if (evt->type == SGL_EVENT_DRAW_MAIN) {
sgl_draw_rect(surf, &obj->area, &body_area, &dropdown->body_desc);
if (dropdown->is_open) {
sgl_draw_icon(surf, &obj->area, icon_area.x1, icon_y + 2, dropdown->text_color, dropdown->body_desc.alpha, &dropdown_icon);
}
else {
sgl_draw_icon(surf, &obj->area, icon_area.x1, icon_y, dropdown->text_color, dropdown->body_desc.alpha, &dropdown_icon);
}
for (int i = 0; option != NULL; i++) {
if (i == dropdown->selected) {
break;
}
option = option->next;
}
if (option != NULL) {
pos_x = text_area.x1 + dropdown->body_desc.radius;
pos_y = obj->coords.y1 + (icon_h - dropdown->font->font_height) / 2;
sgl_draw_string(surf, &text_area, pos_x, pos_y, option->text, dropdown->text_color, dropdown->body_desc.alpha, dropdown->font);
}
if (dropdown->is_open) {
pos_y = body_area.y2;
option = dropdown->expend_start;
body_area.y1 = obj->coords.y1 + dropdown->option_h;
body_area.y2 = body_area.y1 + dropdown->expand_h - 1;
sgl_draw_rect(surf, &obj->area, &body_area, &dropdown->body_desc);
for (int i = 0; option != NULL; i++) {
pos_x = text_area.x1 + dropdown->body_desc.radius;
sgl_draw_string(surf, &obj->area, pos_x, pos_y, option->text, dropdown->text_color, dropdown->body_desc.alpha, dropdown->font);
option = option->next;
pos_y += dropdown->font->font_height;
}
}
}
else if (evt->type == SGL_EVENT_MOVE_UP) {
}
else if (evt->type == SGL_EVENT_MOVE_DOWN) {
}
else if (evt->type == SGL_EVENT_PRESSED || evt->type == SGL_EVENT_CLICKED) {
dropdown->expand_h = dropdown->font->font_height * sgl_min(10, dropdown->option_num);
if (dropdown->is_open) {
dropdown->is_open = false;
obj->coords.y2 -= dropdown->expand_h;
SGL_LOG_INFO("sgl_dropdown_construct_cb: selected %d %d %d", evt->pos.y, obj->coords.y2, dropdown->font->font_height);
if (evt->pos.y > obj->coords.y2) {
dropdown->selected = (evt->pos.y - obj->coords.y2) / dropdown->font->font_height;
}
}
else {
dropdown->is_open = true;
obj->coords.y2 += dropdown->expand_h;
}
sgl_obj_set_dirty(obj);
dropdown->expend_start = dropdown->head;
}
else if (evt->type == SGL_EVENT_DRAW_INIT) {
dropdown->option_h = obj->coords.y2 - obj->coords.y1;
}
}
/**
* @brief create a dropdown object
* @param parent parent of the dropdown
* @return pointer to the dropdown object
*/
sgl_obj_t* sgl_dropdown_create(sgl_obj_t* parent)
{
sgl_dropdown_t *dropdown = sgl_malloc(sizeof(sgl_dropdown_t));
if(dropdown == NULL) {
SGL_LOG_ERROR("sgl_dropdown_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(dropdown, 0, sizeof(sgl_dropdown_t));
sgl_obj_t *obj = &dropdown->obj;
sgl_obj_init(&dropdown->obj, parent);
obj->construct_fn = sgl_dropdown_construct_cb;
obj->needinit = 1;
sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH);
sgl_obj_set_clickable(obj);
sgl_obj_set_movable(obj);
dropdown->body_desc.alpha = SGL_THEME_ALPHA;
dropdown->body_desc.color = SGL_THEME_COLOR;
dropdown->body_desc.radius = 5;
dropdown->body_desc.border = 1;
dropdown->body_desc.border_color = SGL_THEME_BORDER_COLOR;
dropdown->font = sgl_get_system_font();
dropdown->head = NULL;
dropdown->is_open = false;
dropdown->selected = -1;
dropdown->clicked = 0;
return obj;
}
/**
* @brief get the selected text of the dropdown
* @param obj pointer to the dropdown object
* @return pointer to the selected text
*/
const char *sgl_dropdown_get_selected_text(sgl_obj_t *obj)
{
sgl_dropdown_t *dropdown = (sgl_dropdown_t*)obj;
sgl_dropdown_option_t *option = dropdown->head;
for (int i = 0; i < dropdown->option_num; i++) {
if (i == dropdown->selected) {
return option->text;
}
option = option->next;
}
return NULL;
}
/**
* @brief add an option to the dropdown
* @param obj pointer to the dropdown object
* @param text pointer to the text
* @return none
*/
void sgl_dropdown_add_option(sgl_obj_t *obj, const char *text)
{
sgl_dropdown_t *dropdown = (sgl_dropdown_t*)obj;
sgl_dropdown_option_t *tail = dropdown->head;
sgl_dropdown_option_t *add = sgl_malloc(sizeof(sgl_dropdown_option_t));
if (add == NULL) {
SGL_LOG_ERROR("sgl_dropdown_add_option: malloc failed");
return;
}
if (tail == NULL) {
dropdown->head = add;
}
else {
while (tail != NULL) {
if (tail->next == NULL) {
tail->next = add;
break;
}
tail = (tail)->next;
}
}
dropdown->option_num ++;
add->text = text;
add->next = NULL;
if (dropdown->selected == -1) {
dropdown->selected = 0;
}
sgl_obj_set_dirty(obj);
}
/**
* @brief delete an option from the dropdown
* @param obj pointer to the dropdown object
* @param text pointer to the text
* @return none
*/
void sgl_dropdown_delete_option_by_text(sgl_obj_t *obj, const char *text)
{
sgl_dropdown_t *dropdown = (sgl_dropdown_t*)obj;
sgl_dropdown_option_t *curr = dropdown->head;
sgl_dropdown_option_t *temp = dropdown->head;
sgl_dropdown_option_t *prev = NULL;
int deleted_index = 0;
if (obj == NULL || text == NULL) {
return;
}
while (curr != NULL) {
if (curr->text && strcmp(curr->text, text) == 0) {
break;
}
prev = curr;
curr = curr->next;
}
if (curr == NULL) {
return;
}
while (temp != curr) {
temp = temp->next;
deleted_index ++;
}
if (prev == NULL) {
dropdown->head = curr->next;
} else {
prev->next = curr->next;
}
sgl_free(curr);
dropdown->option_num--;
sgl_obj_set_dirty(obj);
}
/**
* @brief delete an option from the dropdown
* @param obj pointer to the dropdown object
* @param index index of the option
* @return none
*/
void sgl_dropdown_delete_option_by_index(sgl_obj_t *obj, int index)
{
sgl_dropdown_t *dropdown = (sgl_dropdown_t*)obj;
sgl_dropdown_option_t *curr = dropdown->head;
sgl_dropdown_option_t *prev = NULL;
if (obj == NULL || index < 0 || index >= dropdown->option_num) {
return;
}
for (int i = 0; i < index; i++) {
prev = curr;
curr = curr->next;
}
if (prev == NULL) {
dropdown->head = curr->next;
} else {
prev->next = curr->next;
}
sgl_free(curr);
dropdown->option_num--;
}

View File

@ -0,0 +1,227 @@
/* source/widgets/sgl_dropdown.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_DROPDOWN_H__
#define __SGL_DROPDOWN_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
typedef struct sgl_dropdown_option {
struct sgl_dropdown_option *next;
const char *text;
} sgl_dropdown_option_t;
/**
* @brief sgl dropdown struct
* @desc: text description
*/
typedef struct sgl_dropdown {
sgl_obj_t obj;
sgl_draw_rect_t body_desc;
const sgl_font_t *font;
sgl_color_t text_color;
sgl_dropdown_option_t *head;
uint16_t option_num;
int16_t selected;
int16_t option_h;
int16_t expand_h;
sgl_dropdown_option_t *expend_start;
uint8_t clicked;
bool is_open;
}sgl_dropdown_t;
/**
* @brief create a dropdown object
* @param parent parent of the dropdown
* @return dropdown object
*/
sgl_obj_t* sgl_dropdown_create(sgl_obj_t* parent);
/**
* @brief set dropdown object's color
* @param obj dropdown object
* @param color color
*/
static inline void sgl_dropdown_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
dropdown->body_desc.color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set dropdown object's border width
* @param obj dropdown object
* @param width border width
*/
static inline void sgl_dropdown_set_border_width(sgl_obj_t *obj, uint8_t width)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
dropdown->body_desc.border = width;
sgl_obj_set_border_width(obj, width);
sgl_obj_set_dirty(obj);
}
/**
* @brief set dropdown object's border color
* @param obj dropdown object
* @param color border color
*/
static inline void sgl_dropdown_set_border_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
dropdown->body_desc.border_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set dropdown object's radius
* @param obj dropdown object
* @param radius radius
*/
static inline void sgl_dropdown_set_radius(sgl_obj_t *obj, uint8_t radius)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
sgl_obj_set_radius(obj, radius);
dropdown->body_desc.radius = obj->radius;
sgl_obj_set_dirty(obj);
}
/**
* @brief set dropdown object's pixmap
* @param obj dropdown object
* @param pixmap pixmap
*/
static inline void sgl_dropdown_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
dropdown->body_desc.pixmap = pixmap;
sgl_obj_set_dirty(obj);
}
/**
* @brief set dropdown object's alpha
* @param obj dropdown object
* @param alpha alpha
*/
static inline void sgl_dropdown_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
dropdown->body_desc.alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set dropdown object's text color
* @param obj dropdown object
* @param color text color
*/
static inline void sgl_dropdown_set_text_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
dropdown->text_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set dropdown object's text font
* @param obj dropdown object
* @param font text font
* @return none
* @note font must be initialized
*/
static inline void sgl_dropdown_set_text_font(sgl_obj_t *obj, const sgl_font_t* font)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
dropdown->font = font;
sgl_obj_set_dirty(obj);
}
/**
* @brief set dropdown object's selected index
* @param obj dropdown object
* @param index selected index
* @return none
*/
static inline void sgl_dropdown_set_selected_index(sgl_obj_t *obj, int index)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
SGL_ASSERT(obj != NULL && index >= 0 && index < dropdown->option_num);
dropdown->selected = index;
sgl_obj_set_dirty(obj);
}
/**
* @brief get dropdown object's selected index
* @param obj dropdown object
* @return selected index
*/
static inline int sgl_dropdown_get_selected_index(sgl_obj_t *obj)
{
sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj);
return dropdown->selected;
}
/**
* @brief get dropdown object's selected text
* @param obj dropdown object
* @return selected text
*/
const char *sgl_dropdown_get_selected_text(sgl_obj_t *obj);
/**
* @brief add an option to the dropdown
* @param obj pointer to the dropdown object
* @param text pointer to the text
* @return none
*/
void sgl_dropdown_add_option(sgl_obj_t *obj, const char *text);
/**
* @brief delete an option from the dropdown
* @param obj pointer to the dropdown object
* @param text pointer to the text
* @return none
*/
void sgl_dropdown_delete_option_by_text(sgl_obj_t *obj, const char *text);
/**
* @brief delete an option from the dropdown
* @param obj pointer to the dropdown object
* @param index index of the option
* @return none
*/
void sgl_dropdown_delete_option_by_index(sgl_obj_t *obj, int index);
#endif // !__SGL_DROPDOWN_H__

View File

@ -0,0 +1,249 @@
/* source/widgets/sgl_ext_img.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_ext_img.h"
static inline void ext_img_rle_init(sgl_ext_img_t *img)
{
SGL_ASSERT(img != NULL);
img->index = 0;
img->remainder = 0;
}
static inline void rle_decompress_line(sgl_ext_img_t *img, sgl_area_t *coords, sgl_area_t *area, sgl_color_t *out)
{
uint8_t tmp_buf[8];
uint8_t* read_ptr = NULL;
uint8_t* start_ptr = (uint8_t*)img->pixmap[img->pixmap_idx].bitmap.array;
uintptr_t start_addr = img->pixmap[img->pixmap_idx].bitmap.addr;
uint8_t format = img->pixmap->format;
uint32_t pix_value;
for (int i = coords->x1; i <= coords->x2; i++) {
if (img->remainder == 0) {
if (img->read != NULL) {
read_ptr = tmp_buf;
img->read(start_addr + img->index, tmp_buf, sizeof(tmp_buf));
}
else {
read_ptr = start_ptr + img->index;
}
img->index ++;
img->remainder = read_ptr[0];
switch (format) {
case SGL_PIXMAP_FMT_RLE_RGB332:
pix_value = read_ptr[1];
img->color = sgl_rgb332_to_color(pix_value);
img->pix_alpha = SGL_ALPHA_MAX;
img->index ++;
break;
case SGL_PIXMAP_FMT_RLE_ARGB2222:
pix_value = read_ptr[1];
img->color = sgl_rgb222_to_color(pix_value);
img->pix_alpha = sgl_opa2_table[pix_value >> 6];
img->index ++;
break;
case SGL_PIXMAP_FMT_RLE_RGB565:
pix_value = read_ptr[1] | (read_ptr[2] << 8);
img->color = sgl_rgb565_to_color(pix_value);
img->pix_alpha = SGL_ALPHA_MAX;
img->index += 2;
break;
case SGL_PIXMAP_FMT_RLE_ARGB4444:
pix_value = read_ptr[1] | (read_ptr[2] << 8);
img->color = sgl_rgb444_to_color(pix_value);
img->pix_alpha = sgl_opa4_table[pix_value >> 12];
img->index += 2;
break;
case SGL_PIXMAP_FMT_RLE_RGB888:
pix_value = read_ptr[1] | (read_ptr[2] << 8) | (read_ptr[3] << 16);
img->color = sgl_rgb888_to_color(pix_value);
img->pix_alpha = SGL_ALPHA_MAX;
img->index += 3;
break;
case SGL_PIXMAP_FMT_RLE_ARGB8888:
pix_value = read_ptr[1] | (read_ptr[2] << 8) | (read_ptr[3] << 16);
img->color = sgl_rgb888_to_color(pix_value);
img->pix_alpha = read_ptr[4];
img->index += 4;
break;
default:
break;
}
}
if (out != NULL && i >= area->x1 && i <= area->x2) {
img->color = (img->pix_alpha == SGL_ALPHA_MAX ? img->color : sgl_color_mixer(img->color, *out, img->pix_alpha));
*out = (img->alpha == SGL_ALPHA_MAX ? img->color : sgl_color_mixer(img->color, *out, img->alpha));
out ++;
}
img->remainder --;
};
}
static void sgl_ext_img_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_area_t clip = SGL_AREA_INVALID;
sgl_ext_img_t *ext_img = sgl_container_of(obj, sgl_ext_img_t, obj);
const sgl_pixmap_t *pixmap = &ext_img->pixmap[ext_img->pixmap_idx];
uintptr_t read_addr = pixmap->bitmap.addr;
uint8_t pix_byte = sgl_pixmal_get_bytes_per_pixel(pixmap);
sgl_color_t tmp_color, *buf = NULL, *blend = NULL;
size_t pix_value = 0;
size_t offset = 0;
sgl_area_t area = {
.x1 = obj->coords.x1,
.y1 = obj->coords.y1,
.x2 = obj->coords.x1 + pixmap->width - 1,
.y2 = obj->coords.y1 + pixmap->height - 1,
};
if(evt->type == SGL_EVENT_DRAW_MAIN) {
if (!sgl_surf_clip(surf, &obj->area, &clip)) {
return;
}
if (pixmap->format < SGL_PIXMAP_FMT_RLE_RGB332) {
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
uint8_t *pixmap_buf = (uint8_t*)pixmap->bitmap.array;
if(ext_img->read != NULL){
pixmap_buf = (uint8_t*)sgl_malloc(pix_byte * (clip.x2 - clip.x1 + 1));
}
for (int y = clip.y1; y <= clip.y2; y++) {
blend = buf;
offset = ((((y - area.y1) * pixmap->width) + (clip.x1 - area.x1)) * pix_byte);
if(ext_img->read != NULL) {
ext_img->read(read_addr + offset, pixmap_buf, pix_byte * (clip.x2 - clip.x1 + 1));
offset = 0;
}
for (int x = clip.x1; x <= clip.x2; x++) {
switch (pixmap->format) {
case SGL_PIXMAP_FMT_RGB332:
pix_value = pixmap_buf[offset];
tmp_color = sgl_rgb332_to_color(pix_value);
break;
case SGL_PIXMAP_FMT_RGB565:
pix_value = pixmap_buf[offset] | (pixmap_buf[offset + 1] << 8);
tmp_color = sgl_rgb565_to_color(pix_value);
break;
case SGL_PIXMAP_FMT_ARGB2222:
pix_value = pixmap_buf[offset];
tmp_color = sgl_rgb222_to_color(pix_value);
tmp_color = sgl_color_mixer(tmp_color, *blend, sgl_opa2_table[pix_value >> 6]);
break;
case SGL_PIXMAP_FMT_ARGB4444:
pix_value = pixmap_buf[offset] | (pixmap_buf[offset + 1] << 8);
tmp_color = sgl_rgb444_to_color(pix_value);
tmp_color = sgl_color_mixer(tmp_color, *blend, sgl_opa4_table[pix_value >> 12]);
break;
case SGL_PIXMAP_FMT_RGB888:
pix_value = pixmap_buf[offset] | (pixmap_buf[offset + 1] << 8) | (pixmap_buf[offset + 2] << 16);
tmp_color = sgl_rgb888_to_color(pix_value);
break;
case SGL_PIXMAP_FMT_ARGB8888:
pix_value = pixmap_buf[offset] | (pixmap_buf[offset + 1] << 8) | (pixmap_buf[offset + 2] << 16);
tmp_color = sgl_rgb888_to_color(pix_value);
tmp_color = sgl_color_mixer(tmp_color, *blend, pixmap_buf[offset + 3]);
break;
default:
break;
}
*blend = ext_img->alpha == SGL_ALPHA_MAX ? tmp_color : sgl_color_mixer(tmp_color, *blend, ext_img->alpha);
offset += pix_byte;
blend ++;
};
buf += surf->w;
}
if(ext_img->read != NULL) {
sgl_free(pixmap_buf);
}
}
else {
/* RLE pixmap support */
if (clip.y1 == surf->dirty->y1 || clip.y1 == obj->area.y1) {
ext_img->index = 0;
ext_img->remainder = 0;
for (int y = area.y1; y < clip.y1; y++) {
rle_decompress_line(ext_img, &area, &clip, NULL);
}
}
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, (clip.y1 - surf->y1));
for (int y = clip.y1; y <= clip.y2; y++) {
rle_decompress_line(ext_img, &area, &clip, buf);
buf += surf->w;
}
}
if (ext_img->pixmap_auto && (clip.y2 == surf->dirty->y2 || clip.y2 == obj->area.y2)) {
uint32_t pixmap_idx = ext_img->pixmap_idx + 1;
ext_img->pixmap_idx = pixmap_idx >= ext_img->pixmap_num ? 0 : pixmap_idx;
sgl_obj_set_dirty(obj);
}
}
}
/**
* @brief create an ext_img object
* @param parent parent of the ext_img
* @return ext_img object
*/
sgl_obj_t* sgl_ext_img_create(sgl_obj_t* parent)
{
sgl_ext_img_t *ext_img = sgl_malloc(sizeof(sgl_ext_img_t));
if(ext_img == NULL) {
SGL_LOG_ERROR("sgl_ext_img_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(ext_img, 0, sizeof(sgl_ext_img_t));
sgl_obj_t *obj = &ext_img->obj;
sgl_obj_init(&ext_img->obj, parent);
obj->construct_fn = sgl_ext_img_construct_cb;
ext_img->alpha = SGL_ALPHA_MAX;
ext_img->pixmap_idx = 0;
ext_img->pixmap_num = 1;
ext_img->pixmap_auto = 0;
return obj;
}

View File

@ -0,0 +1,224 @@
/* source/widgets/sgl_ext_img.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_EXT_IMG_H__
#define __SGL_EXT_IMG_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* description:
* 1. Extern Flash image object:
* you can use this object to draw image from external flash memory
* for example:
* void flash_port_read_data_from_flash(const size_t addr, uint8_t *buf, uint32_t len)
* {
* //read the data to the buf from the addr of flash
* Flash_Read(addr, buf, len);
* }
* sgl_pixmap_t test_pixmap = {
* .width = 142,
* .height = 69,
* .bitmap = addr_of_extern_flash,
* .format = SGL_PIXMAP_FMT_RGB565,
* };
* sgl_obj_t *ext_img = sgl_ext_img_create(NULL);
* sgl_obj_set_pos(ext_img, 10, 10);
* sgl_obj_set_size(ext_img, 142, 69);
* sgl_ext_img_set_pixmap(ext_img, &test_pixmap);
* sgl_ext_img_set_read_ops(ext_img, flash_port_read_data_from_flash);
*
* 2. RLE compress image object:
* you can use this object to draw image from external flash memory
* for example:
* extern const uint8_t pixmap_data[19596];
* sgl_pixmap_t test_pixmap = {
* .width = 142,
* .height = 69,
* .bitmap = pixmap_data,
* .format = SGL_PIXMAP_FMT_RLE_RGB565,
* };
* sgl_obj_t *ext_img = sgl_ext_img_create(NULL);
* sgl_obj_set_pos(ext_img, 10, 10);
* sgl_obj_set_size(ext_img, 142, 69);
* sgl_ext_img_set_pixmap(ext_img, &test_pixmap);
*
* 3. Mult pixmap image object:
* you can use this object to draw image from external flash memory
* for example:
* void flash_port_read_data_from_flash(const size_t addr, uint8_t *buf, uint32_t len)
* {
* //read the data to the buf from the addr of flash
* Flash_Read(addr, buf, len);
* }
* sgl_pixmap_t test_pixmap[128] = {
* {
* .width = 142,
* .height = 69,
* .bitmap = addr_of_extern_flash_1,
* .format = SGL_PIXMAP_FMT_RGB565,
* },
* {
* .width = 142,
* .height = 69,
* .bitmap = addr_of_extern_flash_2,
* .format = SGL_PIXMAP_FMT_RGB565,
* },
* {
* .width = 142,
* .height = 69,
* .bitmap = addr_of_extern_flash_3,
* .format = SGL_PIXMAP_FMT_RGB565,
* },
* ...
* };
* sgl_obj_t *ext_img = sgl_ext_img_create(NULL);
* sgl_obj_set_pos(ext_img, 10, 10);
* sgl_obj_set_size(ext_img, 142, 69);
* sgl_ext_img_set_pixmap(ext_img, test_pixmap);
* sgl_ext_img_set_pixmap_num(ext_img, 128, true);
* sgl_ext_img_set_read_ops(ext_img, flash_port_read_data_from_flash);
*/
/* TODO: add ext img buffer size config */
#define SGL_EXT_IMG_BUFFER_SIZE (CONFIG_SGL_EXT_IMG_BUFFER)
/**
* @brief sgl ext_img struct
* @obj: sgl general object
* @desc: pointer to ext_img draw descriptor
*/
typedef struct sgl_ext_img {
sgl_obj_t obj;
const sgl_pixmap_t *pixmap;
void (*read)(const size_t addr, uint8_t *buf, uint32_t len_bytes);
uint8_t alpha;
uint8_t pixmap_auto;
uint8_t pixmap_idx;
uint8_t pixmap_num;
/* RLE compress context */
sgl_color_t color;
uint8_t remainder;
uint8_t pix_alpha;
uint32_t index;
#if CONFIG_SGL_EXT_IMG_BUFFER
uint8_t flash_buffer[SGL_EXT_IMG_BUFFER_SIZE];
#endif
} sgl_ext_img_t;
/**
* @brief create an ext_img object
* @param parent parent of the ext_img
* @return ext_img object
*/
sgl_obj_t* sgl_ext_img_create(sgl_obj_t* parent);
/**
* @brief set ext_img pixmap
* @param obj ext_img object
* @param pixmap ext_img pixmap
* @return none
*/
static inline void sgl_ext_img_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
SGL_ASSERT(obj != NULL);
((sgl_ext_img_t*)obj)->pixmap = pixmap;
}
/**
* @brief set ext_img read operation
* @param obj ext_img object
* @param read ext_img read operation
* @return none
*/
static inline void sgl_ext_img_set_read_ops(sgl_obj_t *obj, void (*read)(const size_t addr, uint8_t *out, uint32_t len_bytes))
{
SGL_ASSERT(obj != NULL);
((sgl_ext_img_t*)obj)->read = read;
}
/**
* @brief set ext_img alpha
* @param obj ext_img object
* @param alpha ext_img alpha
* @return none
*/
static inline void sgl_ext_img_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
SGL_ASSERT(obj != NULL);
((sgl_ext_img_t*)obj)->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set ext_img pixmap number
* @param obj ext_img object
* @param num ext_img pixmap number
* @param auto_refresh ext_img pixmap auto refresh
* @return none
* @note if auto_refresh is true, the ext_img will refresh automatically after pixmap flush conplete
* @warning the num max is 255
*/
static inline void sgl_ext_img_set_pixmap_num(sgl_obj_t *obj, uint8_t num, bool auto_refresh)
{
SGL_ASSERT(obj != NULL);
((sgl_ext_img_t*)obj)->pixmap_num = num;
((sgl_ext_img_t*)obj)->pixmap_auto = (uint8_t)auto_refresh;
}
/**
* @brief set ext_img next pixmap
* @param obj ext_img object
* @return none
*/
static inline void sgl_ext_img_set_pixmap_next(sgl_obj_t *obj)
{
SGL_ASSERT(obj != NULL);
sgl_ext_img_t *ext_img = sgl_container_of(obj, sgl_ext_img_t, obj);
uint32_t pixmap_idx = ext_img->pixmap_idx + 1;
ext_img->pixmap_idx = pixmap_idx >= ext_img->pixmap_num ? 0 : pixmap_idx;
sgl_obj_set_dirty(obj);
}
/**
* @brief set ext_img pixmap current index
* @param obj ext_img object
* @param index ext_img pixmap index
* @return none
*/
static inline void sgl_ext_img_set_pixmap_index(sgl_obj_t *obj, uint8_t index)
{
SGL_ASSERT(obj != NULL);
sgl_ext_img_t *ext_img = sgl_container_of(obj, sgl_ext_img_t, obj);
ext_img->pixmap_idx = sgl_min(index, ext_img->pixmap_num - 1);
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_EXT_IMG_H__

View File

@ -0,0 +1,81 @@
/* source/widgets/sgl_icon.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_icon.h"
/**
* @brief icon construct callback
* @param surf pointer to surface
* @param obj pointer to object
* @param evt pointer to event
* @return none
*/
static void sgl_icon_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_icon_t *icon = sgl_container_of(obj, sgl_icon_t, obj);
sgl_pos_t icon_pos;
if(evt->type == SGL_EVENT_DRAW_MAIN) {
icon_pos = sgl_get_icon_pos(&obj->area, icon->icon, 0, (sgl_align_type_t)icon->align);
sgl_draw_icon(surf, &obj->area, icon_pos.x, icon_pos.y, icon->color, icon->alpha, icon->icon);
}
}
/**
* @brief create icon object
* @param parent pointer to parent object
* @return pointer to icon object
*/
sgl_obj_t* sgl_icon_create(sgl_obj_t* parent)
{
sgl_icon_t *icon = sgl_malloc(sizeof(sgl_icon_t));
if(icon == NULL) {
SGL_LOG_ERROR("sgl_icon_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(icon, 0, sizeof(sgl_icon_t));
sgl_obj_t *obj = &icon->obj;
sgl_obj_init(&icon->obj, parent);
obj->construct_fn = sgl_icon_construct_cb;
icon->alpha = SGL_THEME_ALPHA;
icon->icon = NULL;
icon->color = SGL_THEME_TEXT_COLOR;
icon->align = SGL_ALIGN_CENTER;
return obj;
}

View File

@ -0,0 +1,107 @@
/* source/widgets/sgl_icon.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_ICON_H__
#define __SGL_ICON_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
typedef struct sgl_icon {
sgl_obj_t obj;
const sgl_icon_pixmap_t *icon;
sgl_color_t color;
uint8_t alpha;
uint8_t align;
} sgl_icon_t;
/**
* @brief create icon object
* @param parent pointer to parent object
* @return pointer to icon object
*/
sgl_obj_t* sgl_icon_create(sgl_obj_t* parent);
/**
* @brief set icon color
* @param obj pointer to icon object
* @param color icon color
* @return none
*/
static inline void sgl_icon_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_icon_t *icon = sgl_container_of(obj, sgl_icon_t, obj);
icon->color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set icon alpha
* @param obj pointer to icon object
* @param alpha icon alpha
* @return none
*/
static inline void sgl_icon_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_icon_t *icon = sgl_container_of(obj, sgl_icon_t, obj);
icon->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set icon pixmap
* @param obj pointer to icon object
* @param icon pointer to icon pixmap
* @return none
*/
static inline void sgl_icon_set_icon(sgl_obj_t *obj, const sgl_icon_pixmap_t *icon)
{
sgl_icon_t *icon_obj = sgl_container_of(obj, sgl_icon_t, obj);
icon_obj->icon = icon;
sgl_obj_set_dirty(obj);
}
/**
* @brief set icon align
* @param obj pointer to icon object
* @param align icon align
* @return none
*/
static inline void sgl_icon_set_align(sgl_obj_t *obj, sgl_align_type_t align)
{
sgl_icon_t *icon_obj = sgl_container_of(obj, sgl_icon_t, obj);
icon_obj->align = align;
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_ICON_H__

View File

@ -0,0 +1,551 @@
/* source/widgets/sgl_keyboard.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <sgl_draw.h>
#include <string.h>
#include "sgl_keyboard.h"
#define KEYBOARD_ICON_ENTER ("\xEE\xA2\x86")
#define KEYBOARD_ICON_NEWLINE ("\xEE\xA6\xB8")
#define KEYBOARD_ICON_BACKSPACE ("\xEE\xA0\xBE")
#define KEYBOARD_ICON_KEYBD ("\xEE\xA6\xB7")
#define KEYBOARD_ICON_LEFT ("\xEE\xA8\xAA")
#define KEYBOARD_ICON_RIGHT ("\xEE\xA8\xAB")
#define KEYBOARD_ICON_INVALID (-1)
#define KEYBOARD_KEYMODE_UPPER (0)
#define KEYBOARD_KEYMODE_LOWER (1)
#define KEYBOARD_KEYMODE_SPEC (2)
#define KEYBOARD_KEYMODE_MAX (3)
#define KEYBOARD_BTN_LINES (4)
#define KEYBOARD_BTN_COLUMNS (12)
#define KEYBOARD_BTN_NUM (40)
#define KEYBOARD_KEY_INVALID (-1)
#define KEYBOARD_KEY_TO_UPPER (255)
#define KEYBOARD_KEY_TO_LOWER (254)
#define KEYBOARD_KEY_TO_SPEC (253)
#define KEYBOARD_KEY_TO_CLOSE (252)
#define KEYBOARD_KEY_MODE(x) ((x) >> 1)
#define KEYBOARD_KEY_BACKSPACE (11)
#define KEYBOARD_KEY_NUMBER_BACKSPACE (10)
#define KEYBOARD_KEY_SPACE (37)
#define KEYBOARD_KEY_NEWLINE (22)
#define KEYBOARD_KEY_ENTER (39)
#define KEYBOARD_KEY_CLOSE (35)
#define KEYBOARD_KEY_LEFT (36)
#define KEYBOARD_KEY_RIGHT (38)
static const uint8_t font_bitmap[] = {
/* U+E83E "" */
0x00, 0x00, 0x05, 0xde, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xec, 0x30, 0x00, 0x03, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x00, 0x00, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x00, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f,
0xff, 0xff, 0xf6, 0x7f, 0xff, 0xff, 0x49, 0xff, 0xff, 0xf0, 0x0d, 0xff, 0xff, 0xfd, 0x00, 0x7f,
0xff, 0x40, 0x2f, 0xff, 0xff, 0x08, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0x50, 0x2e, 0xff, 0xff,
0xf3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x20, 0x1e, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff,
0xff, 0xfc, 0x00, 0x0d, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x00, 0x7f,
0xff, 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x50, 0x1a, 0x00, 0x7f, 0xff, 0xff, 0xf0, 0x2f,
0xff, 0xff, 0xff, 0x50, 0x1d, 0xfc, 0x00, 0x8f, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xe1, 0x1d,
0xff, 0xfc, 0x02, 0xff, 0xff, 0xf0, 0x00, 0xcf, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xfc, 0xef, 0xff,
0xff, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x90, 0x00, 0x00, 0x04, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40,
/* U+E886 "" */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1d, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1d, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x00, 0x1c,
0x30, 0x00, 0x00, 0x1d, 0xfb, 0x00, 0x00, 0x00, 0x6f, 0xf3, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x00,
0x00, 0x08, 0xff, 0x30, 0x1d, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xf4, 0xdf, 0xb0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0xff, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xb0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* U+E9B7 "" */
0x03, 0xcd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xc3, 0x00, 0xef, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
0xff, 0xd0, 0x2e, 0x04, 0xc0, 0xc4, 0x0e, 0x20, 0xdf, 0xf1, 0x1f, 0xfd, 0x01, 0xe0, 0x3c, 0x0c,
0x30, 0xe1, 0x0d, 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x1f,
0xfd, 0x01, 0xe0, 0x3c, 0x0c, 0x30, 0xe1, 0x0d, 0xff, 0x11, 0xff, 0xd0, 0x1e, 0x03, 0xc0, 0xc3,
0x0e, 0x10, 0xdf, 0xf1, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0xff,
0xff, 0xff, 0xee, 0xee, 0xee, 0xef, 0xff, 0xff, 0xf1, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00,
0xef, 0xff, 0xff, 0x10, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x0e, 0xff, 0xff, 0xf0, 0x0e, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x4c, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xf6, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00,
/* U+E9B8 "" */
0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xfb, 0x00, 0x00,
0x00, 0x00, 0x0b, 0xd1, 0x00, 0x00, 0xaf, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xf1, 0x00, 0x0a,
0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xf1, 0x00, 0xaf, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0d, 0xf1, 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x08, 0xff, 0xfe, 0xee,
0xee, 0xee, 0xee, 0xee, 0xee, 0xe1, 0x00, 0x8f, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0xfe, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xe3, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* U+EA2A "" */
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x1c, 0xf8, 0x00, 0x01, 0xcf, 0xc0, 0x00, 0x1c, 0xfc, 0x00,
0x01, 0xcf, 0xc0, 0x00, 0x0c, 0xfc, 0x00, 0x00, 0x0b, 0xfd, 0x10, 0x00, 0x00, 0xbf, 0xd1, 0x00,
0x00, 0x0b, 0xfd, 0x10, 0x00, 0x00, 0xbf, 0xd1, 0x00, 0x00, 0x0b, 0xf8, 0x00, 0x00, 0x00, 0x70,
/* U+EA2B "" */
0x08, 0x10, 0x00, 0x00, 0x8f, 0xc1, 0x00, 0x00, 0x0c, 0xfc, 0x10, 0x00, 0x00, 0xcf, 0xc1, 0x00,
0x00, 0x0c, 0xfc, 0x10, 0x00, 0x00, 0xcf, 0xc0, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x1d, 0xfb, 0x00,
0x01, 0xdf, 0xb0, 0x00, 0x1d, 0xfb, 0x00, 0x00, 0x8f, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00
};
static const sgl_font_table_t font_table[] = {
{.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 = 192, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0},
{.bitmap_index = 0, .adv_w = 368, .box_w = 23, .box_h = 18, .ofs_x = 0, .ofs_y = -1},
{.bitmap_index = 207, .adv_w = 368, .box_w = 18, .box_h = 14, .ofs_x = 3, .ofs_y = 1},
{.bitmap_index = 333, .adv_w = 368, .box_w = 21, .box_h = 20, .ofs_x = 1, .ofs_y = -3},
{.bitmap_index = 543, .adv_w = 368, .box_w = 20, .box_h = 12, .ofs_x = 1, .ofs_y = 2},
{.bitmap_index = 663, .adv_w = 368, .box_w = 8, .box_h = 12, .ofs_x = 7, .ofs_y = 2},
{.bitmap_index = 711, .adv_w = 368, .box_w = 8, .box_h = 12, .ofs_x = 8, .ofs_y = 2}
};
static const uint32_t unicode_list_0[] = {
0x0000, 0xe81e, 0xe866, 0xe997, 0xe998, 0xea0a, 0xea0b
};
static const sgl_font_unicode_t font_unicode[] = {
{ .offset = 0x20, .len = 7, .list = unicode_list_0, .tab_offset = 1, }
};
const sgl_font_t keyboard_icon = {
.bitmap = font_bitmap,
.table = font_table,
.font_table_size = SGL_ARRAY_SIZE(font_table),
.font_height = 20,
.base_line = 2,
.bpp = 4,
.compress = 0,
.unicode = font_unicode,
.unicode_num = SGL_ARRAY_SIZE(font_unicode),
};
static const char keyboard_key_ascii[KEYBOARD_KEYMODE_MAX][KEYBOARD_BTN_NUM] = {
{
KEYBOARD_KEY_TO_SPEC, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '\b',
KEYBOARD_KEY_TO_LOWER, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '\n',
'_', '-', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '.', ',', ':',
KEYBOARD_KEY_TO_CLOSE, KEYBOARD_KEY_LEFT, ' ', KEYBOARD_KEY_RIGHT, '\r'
},
{
KEYBOARD_KEY_TO_SPEC, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '\b',
KEYBOARD_KEY_TO_UPPER, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '\n',
'_', '-', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '.', ',', ':',
KEYBOARD_KEY_TO_CLOSE, KEYBOARD_KEY_LEFT, ' ', KEYBOARD_KEY_RIGHT, '\r'
},
{
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\b',
KEYBOARD_KEY_TO_LOWER, '+', '-', '/', '*', '=', '%', '!', '?', '#', '<', '>',
'\\', '@', '$', '(', ')', '{', '}', '[', ']', ';', '\"', '\'',
KEYBOARD_KEY_TO_CLOSE, KEYBOARD_KEY_LEFT, ' ', KEYBOARD_KEY_RIGHT, '\r'
},
};
static const char keybd_btn_map[KEYBOARD_KEYMODE_MAX][KEYBOARD_BTN_NUM][4] = {
{
"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "<<",
"abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", "nl",
"_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":",
"kbd", "<", " ", ">", "OK"
},
{
"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "<<",
"ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", "nl",
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":",
"kbd", "<", " ", ">", "OK"
},
{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "<<",
"abc", "+", "-", "/", "*", "=", "%", "!", "?", "#", "<", ">",
"\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'",
"kbd", "<", " ", ">", "OK"
},
};
static const uint8_t keybd_btn_width[2][KEYBOARD_BTN_LINES][KEYBOARD_BTN_COLUMNS] = {
/* upper and lower mode */
{
{5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7},
{6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 6, 2, 2},
},
/* number mode and spec mode */
{
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 6, 2, 2},
},
};
static const uint8_t keybd_btn_height[KEYBOARD_BTN_LINES] = {
1, 1, 1, 1
};
static const uint8_t keyboard_btn_count[2][KEYBOARD_BTN_LINES] = {
/* upper and lower mode */
{
12, 11, 12, 5
},
/* number mode and spec mode */
{
11, 12, 12, 5
}
};
static void keyboard_btn_handler(sgl_keyboard_t *keyboard)
{
char *edit = keyboard->edit;
int index = keyboard->edit_max_len;
while (*edit && index) {
edit ++;
index --;
}
if (keyboard->opcode == '\b') {
*(--edit) = '\0';
return;
}
if (index == 0) {
SGL_LOG_ERROR("keyboard edit buffer is full\n");
return;
}
switch (keyboard->opcode) {
case '\n':
case '\r':
*(edit++) = '\n';
*(edit++) = '\0';
break;
default :
*(edit++) = keyboard->opcode;
*(edit++) = '\0';
break;
}
}
static const char* keyindex_is_icon(uint8_t mode, uint8_t index)
{
if(index == KEYBOARD_KEY_NUMBER_BACKSPACE && (mode == KEYBOARD_KEYMODE_SPEC)) {
return KEYBOARD_ICON_BACKSPACE;
}
else if(index == KEYBOARD_KEY_BACKSPACE && (mode < KEYBOARD_KEYMODE_SPEC)) {
return KEYBOARD_ICON_BACKSPACE;
}
else if(index == KEYBOARD_KEY_ENTER) {
return KEYBOARD_ICON_ENTER;
}
else if(index == KEYBOARD_KEY_NEWLINE && (mode != KEYBOARD_KEYMODE_SPEC)) {
return KEYBOARD_ICON_NEWLINE;
}
else if(index == KEYBOARD_KEY_CLOSE) {
return KEYBOARD_ICON_KEYBD;
}
else if(index == KEYBOARD_KEY_LEFT) {
return KEYBOARD_ICON_LEFT;
}
else if(index == KEYBOARD_KEY_RIGHT) {
return KEYBOARD_ICON_RIGHT;
}
return NULL;
}
static inline uint8_t keyboard_index_to_ascii(uint8_t keymode, uint8_t index)
{
return keyboard_key_ascii[keymode][index];
}
static int8_t keyboard_pos_to_index(int16_t x, int16_t y, sgl_keyboard_t *keyboard, int16_t width, int16_t height)
{
sgl_obj_t *obj = &keyboard->obj;
int16_t index = 0, x_index = -1, y_index = -1, key_mode = KEYBOARD_KEY_MODE(keyboard->key_mode);
int16_t btn_width[KEYBOARD_BTN_COLUMNS] = {0};
int16_t btn_height[KEYBOARD_BTN_LINES] = {0};
sgl_rect_t btn = {0};
/* calculate button height */
sgl_split_len(keybd_btn_height, KEYBOARD_BTN_LINES, height, keyboard->key_margin, btn_height);
btn.y1 = obj->coords.y1;
for(int i = 0; i < KEYBOARD_BTN_LINES; i++) {
btn.y1 += keyboard->key_margin;
btn.y2 = btn.y1 + btn_height[i] - 1;
if(y >= btn.y1 && y <= btn.y2) {
y_index = i;
break;
}
btn.y1 += btn_height[i];
}
if(y_index < 0 || y_index >= KEYBOARD_BTN_LINES) {
return -1;
}
sgl_split_len(keybd_btn_width[key_mode][y_index], keyboard_btn_count[key_mode][y_index], width, keyboard->key_margin, btn_width);
btn.x1 = obj->coords.x1;
for(int i = 0; i < keyboard_btn_count[key_mode][y_index]; i++) {
btn.x1 += keyboard->key_margin;
btn.x2 = btn.x1 + btn_width[i] - 1;
if(x >= btn.x1 && x <= btn.x2) {
x_index = i;
break;
}
btn.x1 += btn_width[i];
}
if(x_index < 0 || x_index >= keyboard_btn_count[key_mode][y_index]) {
return -1;
}
for(int i = 0; i < y_index; i ++) {
index += keyboard_btn_count[key_mode][i];
}
return (index + x_index);
}
/**
* @brief keyboard constructor function
* @param surf: pointer to surface
* @param obj: pointer to keyboard object
* @param evt: pointer to event
* @return none
*/
static void sgl_keyboard_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
int16_t body_w = obj->coords.x2 - obj->coords.x1 + 1;
int16_t body_h = obj->coords.y2 - obj->coords.y1 + 1;
int8_t index = 0, key_mode = KEYBOARD_KEY_MODE(keyboard->key_mode);
sgl_color_t btn_color = keyboard->btn_desc.color;
int16_t text_x = 0, text_y = 0;
const char *text = NULL;
const sgl_font_t *font = keyboard->font;
int16_t btn_width[KEYBOARD_BTN_COLUMNS] = {0};
int16_t btn_height[KEYBOARD_BTN_LINES] = {0};
sgl_rect_t btn_coords = {0}, btn_area = {0};
/* calculate button height */
sgl_split_len(keybd_btn_height, KEYBOARD_BTN_LINES, body_h, keyboard->key_margin, btn_height);
if(evt->type == SGL_EVENT_DRAW_MAIN) {
sgl_draw_rect(surf, &obj->area, &obj->coords, &keyboard->body_desc);
btn_coords.y1 = obj->coords.y1;
for(int i = 0; i < KEYBOARD_BTN_LINES; i++) {
sgl_split_len(keybd_btn_width[key_mode][i], keyboard_btn_count[key_mode][i], body_w, keyboard->key_margin, btn_width);
btn_coords.x1 = obj->coords.x1;
btn_coords.y1 += keyboard->key_margin;
btn_coords.y2 = btn_coords.y1 + btn_height[i] - 1;
for(int j = 0; j < keyboard_btn_count[key_mode][i]; j++) {
btn_coords.x1 += keyboard->key_margin;
btn_coords.x2 = btn_coords.x1 + btn_width[j] - 1;
btn_area = btn_coords;
if (!sgl_area_selfclip(&btn_area, &obj->area)) {
sgl_area_init(&btn_area);
}
if(index == keyboard->key_index) {
keyboard->btn_desc.color = sgl_color_mixer(btn_color, keyboard->text_color, 128);
}
else {
keyboard->btn_desc.color = btn_color;
}
sgl_draw_rect(surf, &btn_area, &btn_coords, &keyboard->btn_desc);
text = keyindex_is_icon(keyboard->key_mode, index);
if (text != NULL) {
font = &keyboard_icon;
}
else {
font = keyboard->font;
text = keybd_btn_map[keyboard->key_mode][index];
}
text_x = btn_coords.x1 + (btn_width[j] - sgl_font_get_string_width(text, font)) / 2;
text_y = btn_coords.y1 + (btn_height[i] - font->font_height) / 2;
sgl_draw_string(surf, &btn_area, text_x, text_y, text, keyboard->text_color, SGL_ALPHA_MAX, font);
btn_coords.x1 += btn_width[j];
index ++;
}
btn_coords.y1 += btn_height[i];
}
keyboard->btn_desc.color = btn_color;
}
else if(evt->type == SGL_EVENT_PRESSED || evt->type == SGL_EVENT_OPTION_TAP) {
if (evt->type == SGL_EVENT_PRESSED) {
index = keyboard_pos_to_index(evt->pos.x, evt->pos.y, keyboard, body_w, body_h);
if(index < 0) {
return;
}
keyboard->key_index = index;
}
uint8_t key_ascii = keyboard_index_to_ascii(keyboard->key_mode, index);
if(key_ascii == KEYBOARD_KEY_TO_UPPER) {
keyboard->key_mode = KEYBOARD_KEYMODE_UPPER;
keyboard->key_index = KEYBOARD_KEY_INVALID;
}
else if(key_ascii == KEYBOARD_KEY_TO_LOWER) {
keyboard->key_mode = KEYBOARD_KEYMODE_LOWER;
keyboard->key_index = KEYBOARD_KEY_INVALID;
}
else if(key_ascii == KEYBOARD_KEY_TO_SPEC) {
keyboard->key_mode = KEYBOARD_KEYMODE_SPEC;
keyboard->key_index = KEYBOARD_KEY_INVALID;
}
else if(key_ascii == KEYBOARD_KEY_TO_CLOSE) {
sgl_obj_set_destroyed(obj);
return;
}
else {
keyboard->opcode = key_ascii;
if (keyboard->edit) {
keyboard_btn_handler(keyboard);
}
}
sgl_obj_set_dirty(obj);
}
else if(evt->type == SGL_EVENT_RELEASED) {
keyboard->key_index = KEYBOARD_KEY_INVALID;
sgl_obj_set_dirty(obj);
}
else if(evt->type == SGL_EVENT_DRAW_INIT) {
keyboard->opcode = 0;
keyboard->key_index = KEYBOARD_KEY_INVALID;
if (keyboard->key_margin == 0) {
keyboard->key_margin = sgl_max(body_w / 128, 1);
}
if (keyboard->btn_desc.radius == 0) {
keyboard->btn_desc.radius = sgl_max(keyboard->key_margin, 2);
}
SGL_ASSERT(keyboard->font != NULL);
}
else if (evt->type == SGL_EVENT_OPTION_WALK) {
keyboard->key_index ++;
if (keyboard->key_index >= KEYBOARD_BTN_NUM) {
keyboard->key_index = 0;
}
sgl_obj_set_dirty(obj);
}
}
/**
* @brief create keyboard object
* @param parent parent of object
* @return keyboard object
*/
sgl_obj_t* sgl_keyboard_create(sgl_obj_t* parent)
{
sgl_keyboard_t *keyboard = sgl_malloc(sizeof(sgl_keyboard_t));
if(keyboard == NULL) {
SGL_LOG_ERROR("sgl_keyboard_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(keyboard, 0, sizeof(sgl_keyboard_t));
sgl_obj_t *obj = &keyboard->obj;
sgl_obj_init(&keyboard->obj, parent);
obj->construct_fn = sgl_keyboard_construct_cb;
sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH);
obj->clickable = 1;
obj->needinit = 1;
keyboard->body_desc.alpha = SGL_THEME_ALPHA;
keyboard->body_desc.color = SGL_THEME_COLOR;
keyboard->body_desc.radius = SGL_THEME_RADIUS;
keyboard->body_desc.border = 1;
keyboard->body_desc.border_color = SGL_THEME_BORDER_COLOR;
keyboard->body_desc.pixmap = NULL;
keyboard->text_color = SGL_THEME_TEXT_COLOR;
keyboard->btn_desc.alpha = SGL_THEME_ALPHA;
keyboard->btn_desc.color = sgl_color_mixer(SGL_THEME_BORDER_COLOR, SGL_THEME_COLOR, 64);
keyboard->btn_desc.radius = 4;
keyboard->btn_desc.border = 0;
keyboard->btn_desc.border_color = SGL_THEME_BORDER_COLOR;
keyboard->btn_desc.pixmap = NULL;
keyboard->key_mode = KEYBOARD_KEYMODE_LOWER;
keyboard->key_margin = 0;
keyboard->font = sgl_get_system_font();
return obj;
}

View File

@ -0,0 +1,275 @@
/* source/widgets/sgl_keyboard.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_KEYBOARD_H__
#define __SGL_KEYBOARD_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief sgl keyboard struct
* @obj: sgl general object
* @body_desc: pointer to sgl_draw_rect_t descriptor
*/
typedef struct sgl_keyboard {
sgl_obj_t obj;
sgl_draw_rect_t body_desc;
sgl_draw_rect_t btn_desc;
const sgl_font_t *font;
char *edit;
sgl_color_t text_color;
uint8_t opcode;
uint8_t key_margin;
int8_t key_index;
uint8_t key_mode;
uint32_t edit_max_len;
} sgl_keyboard_t;
/**
* @brief create keyboard object
* @param parent parent of object
* @return keyboard object
*/
sgl_obj_t* sgl_keyboard_create(sgl_obj_t* parent);
/**
* @brief set keyboard color
* @param obj keyboard object
* @param color color
* @return none
*/
static inline void sgl_keyboard_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->body_desc.color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard alpha
* @param obj keyboard object
* @param alpha alpha [0 ~ 255]
* @return none
*/
static inline void sgl_keyboard_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->body_desc.alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard radius
* @param obj keyboard object
* @param radius radius [0 ~ 255]
* @return none
*/
static inline void sgl_keyboard_set_radius(sgl_obj_t *obj, uint8_t radius)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
sgl_obj_set_radius(obj, radius);
keyboard->body_desc.radius = obj->radius;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard pixmap
* @param obj keyboard object
* @param pixmap pixmap
* @return none
*/
static inline void sgl_keyboard_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->body_desc.pixmap = pixmap;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard border color
* @param obj keyboard object
* @param color border color
* @return none
*
*/
static inline void sgl_keyboard_set_border_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->body_desc.border_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard border width
* @param obj keyboard object
* @param width border width [0 ~ 255]
* @return none
*/
static inline void sgl_keyboard_set_border_width(sgl_obj_t *obj, uint8_t width)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->btn_desc.border = width;
sgl_obj_set_border_width(obj, width);
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard text color
* @param obj keyboard object
* @param color text color
* @return none
*/
static inline void sgl_keyboard_set_text_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->text_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard text font
* @param obj keyboard object
* @param font text font
* @return none
*/
static inline void sgl_keyboard_set_text_font(sgl_obj_t *obj, const sgl_font_t *font)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->font = font;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard button radius
* @param obj keyboard object
* @param radius button radius [0 ~ 255]
* @return none
*/
static inline void sgl_keyboard_set_btn_radius(sgl_obj_t *obj, uint8_t radius)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->btn_desc.radius = radius;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard button alpha
* @param obj keyboard object
* @param alpha button alpha [0 ~ 255]
* @return none
*/
static inline void sgl_keyboard_set_btn_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->btn_desc.alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard button color
* @param obj keyboard object
* @param color button color
* @return none
*/
static inline void sgl_keyboard_set_btn_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->btn_desc.color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard button pixmap
* @param obj keyboard object
* @param pixmap button pixmap
* @return none
*/
static inline void sgl_keyboard_set_btn_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->btn_desc.pixmap = pixmap;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard button border color
* @param obj keyboard object
* @param color button border color
* @return none
*/
static inline void sgl_keyboard_set_btn_border_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->btn_desc.border_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set keyboard button border width
* @param obj keyboard object
* @param width button border width [0 ~ 255]
* @return none
*/
static inline void sgl_keyboard_set_btn_border_width(sgl_obj_t *obj, uint8_t width)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->btn_desc.border = width;
sgl_obj_set_dirty(obj);
}
/**
* @brief get keyboard opcode
* @param obj keyboard object
* @return opcode [0 ~ 255]
*/
static inline uint8_t sgl_keyboard_get_opcode(sgl_obj_t *obj)
{
return ((sgl_keyboard_t*)obj)->opcode;
}
/**
* @brief set keyboard text buffer
* @param obj keyboard object
* @param buffer edit buffer
* @param buf_max_len edit buffer max length
*/
static inline void sgl_keyboard_set_textarea(sgl_obj_t *obj, char *buffer, int buf_max_len)
{
sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj);
keyboard->edit = buffer;
keyboard->edit_max_len = buf_max_len;
}
#endif // !__SGL_KEYBOARD_H__

View File

@ -0,0 +1,131 @@
/* source/widgets/sgl_label.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_label.h"
/**
* @brief construct the label object
* @param surf pointer to the surface
* @param obj pointer to the label object
* @param evt pointer to the event
* @return none
*/
static void sgl_label_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
sgl_pos_t align_pos;
SGL_ASSERT(label->font != NULL);
if (evt->type == SGL_EVENT_DRAW_MAIN) {
if (label->bg_flag) {
sgl_draw_fill_rect(surf, &obj->area, &obj->coords, obj->radius, label->bg_color, label->alpha);
}
align_pos = sgl_get_text_pos(&obj->coords, label->font, label->text, 0, (sgl_align_type_t)label->align);
#if (CONFIG_SGL_LABEL_ROTATION)
if (label->rota == 0) {
#endif
sgl_draw_string(surf, &obj->area, align_pos.x + label->transform.offset.offset_x,
align_pos.y + label->transform.offset.offset_y,
label->text, label->color, label->alpha, label->font);
#if (CONFIG_SGL_LABEL_ROTATION)
}
else {
const int16_t width = obj->area.x2 - obj->area.x1 + 1;
const int16_t height = obj->area.y2 - obj->area.y1 + 1;
const uint32_t buf_size = width * height;
sgl_color_t *temp_buf = sgl_malloc(buf_size * sizeof(sgl_color_t));
if (temp_buf == NULL) {
SGL_LOG_ERROR("sgl_label_construct_cb: malloc rotation temp buffer failed");
return;
}
for (uint32_t i = 0; i < buf_size; i++) {
temp_buf[i] = label->bg_color;
}
sgl_surf_t temp_surf = {
.x1 = 0,
.y1 = 0,
.x2 = width - 1,
.y2 = height - 1,
.buffer = temp_buf,
.w = width,
.h = height,
.dirty = NULL
};
sgl_draw_string(&temp_surf, &obj->area, align_pos.x, align_pos.y,
label->text, label->color, label->alpha, label->font);
sgl_draw_xform_surf(surf, &temp_surf, &obj->area, obj->coords.x1, obj->coords.y1, label->transform.rotation);
sgl_free(temp_buf);
}
#endif
}
}
/**
* @brief create a label object
* @param parent parent of the label
* @return pointer to the label object
*/
sgl_obj_t* sgl_label_create(sgl_obj_t* parent)
{
sgl_label_t *label = sgl_malloc(sizeof(sgl_label_t));
if(label == NULL) {
SGL_LOG_ERROR("sgl_label_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(label, 0, sizeof(sgl_label_t));
sgl_obj_t *obj = &label->obj;
sgl_obj_init(&label->obj, parent);
obj->construct_fn = sgl_label_construct_cb;
label->alpha = SGL_ALPHA_MAX;
label->bg_flag = 0;
label->color = SGL_THEME_TEXT_COLOR;
label->text = "";
label->transform.rotation = 0;
label->rota = 0;
label->font = sgl_get_system_font();
return obj;
}

View File

@ -0,0 +1,191 @@
/* source/widgets/sgl_label.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_LABEL_H__
#define __SGL_LABEL_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief sgl label object
* @obj: sgl general object
* @desc: draw task descriptor
*/
typedef struct sgl_label {
sgl_obj_t obj;
const char *text;
const sgl_font_t *font;
sgl_color_t color;
sgl_color_t bg_color;
uint8_t alpha;
uint8_t align: 6;
uint8_t bg_flag : 1;
uint8_t rota : 1;
union {
struct {
int8_t offset_x;
int8_t offset_y;
} offset;
int16_t rotation;
} transform;
}sgl_label_t;
/**
* @brief create a label object
* @param parent parent of the label
* @return pointer to the label object
*/
sgl_obj_t* sgl_label_create(sgl_obj_t* parent);
/**
* @brief set label text
* @param obj pointer to the label object
* @param text text to be set
* @return none
*/
static inline void sgl_label_set_text(sgl_obj_t *obj, const char *text)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
label->text = text;
sgl_obj_set_dirty(obj);
}
/**
* @brief set label font
* @param obj pointer to the label object
* @param font pointer to the font
* @return none
*/
static inline void sgl_label_set_font(sgl_obj_t *obj, const sgl_font_t *font)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
label->font = font;
sgl_obj_set_dirty(obj);
}
/**
* @brief set label text color
* @param obj pointer to the label object
* @param color color to be set
* @return none
*/
static inline void sgl_label_set_text_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
label->color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set label background color
* @param obj pointer to the label object
* @param color color to be set
* @return none
*/
static inline void sgl_label_set_bg_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
label->bg_color = color;
label->bg_flag = 1;
sgl_obj_set_dirty(obj);
}
/**
* @brief set label radius
* @param obj pointer to the label object
* @param radius radius to be set
* @return none
*/
static inline void sgl_label_set_radius(sgl_obj_t *obj, uint8_t radius)
{
sgl_obj_set_radius(obj, radius);
sgl_obj_set_dirty(obj);
}
/**
* @brief set label text align
* @param obj pointer to the label object
* @param align align to be set
* @return none
*/
static inline void sgl_label_set_text_align(sgl_obj_t *obj, sgl_align_type_t align)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
label->align = align;
sgl_obj_set_dirty(obj);
}
/**
* @brief set label alpha
* @param obj pointer to the label object
* @param alpha alpha to be set
* @return none
*/
static inline void sgl_label_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
label->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set label text offset
* @param obj pointer to the label object
* @param offset_x offset_x to be set
* @param offset_y offset_y to be set
* @return none
*/
static inline void sgl_label_set_text_offset(sgl_obj_t *obj, int8_t offset_x, int8_t offset_y)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
label->transform.offset.offset_x = offset_x;
label->transform.offset.offset_y = offset_y;
sgl_obj_set_dirty(obj);
}
/**
* @brief set label text rotation
* @param obj pointer to the label object
* @param text_rotation text rotation angle (0-360 degree)
* @return none
*/
static inline void sgl_label_set_text_rotation(sgl_obj_t *obj, int16_t text_rotation)
{
sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj);
label->transform.rotation = text_rotation % 360;
if (label->transform.rotation < 0) label->transform.rotation += 360;
label->rota = label->transform.rotation ? 1 : 0;
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_LABEL_H__

View File

@ -0,0 +1,136 @@
/* source/widgets/sgl_led.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: docs directory
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_led.h"
static void sgl_led_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj);
int16_t cx = 0, cy = 0;
sgl_color_t color = led->status ? led->on_color : led->off_color;
sgl_color_t *buf = NULL, *blend = NULL;
if(evt->type == SGL_EVENT_DRAW_MAIN) {
sgl_area_t clip;
cx = (led->obj.coords.x1 + led->obj.coords.x2) / 2;
cy = (led->obj.coords.y1 + led->obj.coords.y2) / 2;
if (!sgl_surf_clip(surf, &obj->area, &clip)) {
return;
}
sgl_area_t c_rect = {
.x1 = cx - obj->radius,
.x2 = cx + obj->radius,
.y1 = cy - obj->radius,
.y2 = cy + obj->radius
};
if (!sgl_area_selfclip(&clip, &c_rect)) {
return;
}
int y2 = 0, real_r2 = 0, edge_alpha = 0;
int r2 = sgl_pow2(obj->radius);
int r2_edge = sgl_pow2(obj->radius + 1);
int ds_alpha = SGL_ALPHA_MIN;
buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1);
for (int y = clip.y1; y <= clip.y2; y++) {
y2 = sgl_pow2(y - cy);
blend = buf;
for (int x = clip.x1; x <= clip.x2; x++, blend++) {
real_r2 = sgl_pow2(x - cx) + y2;
if (real_r2 >= r2_edge) {
if(x > cx)
break;
continue;
}
else if (real_r2 >= r2) {
edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2);
sgl_color_t color_mix = sgl_color_mixer(led->bg_color, *blend, edge_alpha);
*blend = sgl_color_mixer(color_mix, *blend, led->alpha);
}
else {
ds_alpha = real_r2 * SGL_ALPHA_NUM / r2;
ds_alpha = sgl_pow2(ds_alpha) / SGL_ALPHA_NUM ;
*blend = sgl_color_mixer(sgl_color_mixer(led->bg_color, color, ds_alpha), *blend, led->alpha);//SGL_THEME_BG_COLOR
}
}
buf += surf->w;
}
}
else if (evt->type == SGL_EVENT_DRAW_INIT) {
if (obj->radius == SGL_RADIUS_INVALID) {
sgl_obj_set_radius(obj, SGL_POS_MAX);
}
}
else if (evt->type == SGL_EVENT_PRESSED || evt->type == SGL_EVENT_RELEASED) {
if (obj->event_fn) {
obj->event_fn(evt);
}
}
}
/**
* @brief create a led object
* @param parent parent of the led
* @return led object
*/
sgl_obj_t* sgl_led_create(sgl_obj_t* parent)
{
sgl_led_t *led = sgl_malloc(sizeof(sgl_led_t));
if(led == NULL) {
SGL_LOG_ERROR("sgl_led_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(led, 0, sizeof(sgl_led_t));
sgl_obj_t *obj = &led->obj;
sgl_obj_init(&led->obj, parent);
obj->construct_fn = sgl_led_construct_cb;
obj->needinit = 1;
led->alpha = SGL_ALPHA_MAX;
led->on_color = SGL_THEME_COLOR;
led->off_color = SGL_THEME_BG_COLOR;
led->bg_color = SGL_THEME_BG_COLOR;
obj->radius = SGL_RADIUS_INVALID;
return obj;
}

View File

@ -0,0 +1,157 @@
/* source/widgets/sgl_led.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: docs directory
*
* 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.
*/
#ifndef __SGL_LED_H__
#define __SGL_LED_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief sgl led struct
* @obj: sgl general object
* @desc: pointer to led draw descriptor
*/
typedef struct sgl_led {
sgl_obj_t obj;
uint8_t alpha;
bool status;
sgl_color_t on_color;
sgl_color_t off_color;
sgl_color_t bg_color;
}sgl_led_t;
/**
* @brief create a led object
* @param parent parent of the led
* @return led object
*/
sgl_obj_t* sgl_led_create(sgl_obj_t* parent);
/**
* @brief set the color of the led
* @param obj led object
* @param color color of the led
* @return none
*/
static inline void sgl_led_set_on_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj);
led->on_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the off color of the led
* @param obj led object
* @param color off color of the led
* @return none
*/
static inline void sgl_led_set_off_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj);
led->off_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief Set the background color of the led
* @param obj led object
* @param color background color of the led
* @return none
*/
static inline void sgl_led_set_bg_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj);
led->bg_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the alpha of the led
* @param obj led object
* @param alpha alpha of the led
* @return none
*/
static inline void sgl_led_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj);
led->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set the status of the led
* @param obj led object
* @param status status of the led
* @return none
*/
static inline void sgl_led_set_status(sgl_obj_t *obj, bool status)
{
sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj);
led->status = status;
sgl_obj_set_dirty(obj);
}
/**
* @brief get the status of the led
* @param obj led object
* @return status of the led
*/
static inline bool sgl_led_get_status(sgl_obj_t *obj)
{
sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj);
return led->status;
}
/**
* @brief turn on the led
* @param obj led object
* @return none
*/
static inline void sgl_led_on(sgl_obj_t *obj)
{
sgl_led_set_status(obj, true);
}
/**
* @brief turn off the led
* @param obj led object
* @return none
*/
static inline void sgl_led_off(sgl_obj_t *obj)
{
sgl_led_set_status(obj, false);
}
#endif // !__SGL_LED_H__

View File

@ -0,0 +1,132 @@
/* source/widgets/sgl_line.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_theme.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_line.h"
static void sgl_line_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_line_t *line = sgl_container_of(obj, sgl_line_t, obj);
sgl_draw_line_t desc;
desc.x1 = obj->coords.x1;
desc.y1 = obj->coords.y1;
desc.x2 = obj->coords.x2;
desc.y2 = obj->coords.y2;
desc.color = line->color;
desc.alpha = line->alpha;
desc.width = obj->border;
if(evt->type == SGL_EVENT_DRAW_MAIN) {
if (line->x_swap) {
sgl_swap(&desc.x1, &desc.x2);
}
if (line->y_swap) {
sgl_swap(&desc.y1, &desc.y2);
}
sgl_draw_line(surf, &obj->parent->area, &desc);
}
}
/**
* @brief create a line object
* @param parent parent of the line
* @return line object
*/
sgl_obj_t* sgl_line_create(sgl_obj_t* parent)
{
sgl_line_t *line = sgl_malloc(sizeof(sgl_line_t));
if(line == NULL) {
SGL_LOG_ERROR("sgl_line_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(line, 0, sizeof(sgl_line_t));
sgl_obj_t *obj = &line->obj;
sgl_obj_init(&line->obj, parent);
obj->construct_fn = sgl_line_construct_cb;
line->color = SGL_THEME_BG_COLOR;
line->alpha = SGL_ALPHA_MAX;
obj->border = 1;
return obj;
}
/**
* @brief set line start position
* @param obj line object
* @param x start x position
* @param y start y position
* @return none
*/
void sgl_line_set_pos(sgl_obj_t *obj, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
{
SGL_ASSERT(obj != NULL);
int16_t _x1, _y1, _x2, _y2;
sgl_line_t *line = sgl_container_of(obj, sgl_line_t, obj);
_x1 = obj->parent->coords.x1 + x1;
_x2 = obj->parent->coords.x1 + x2;
_y1 = obj->parent->coords.y1 + y1;
_y2 = obj->parent->coords.y1 + y2;
if (_x1 > _x2) {
sgl_swap(&_x1, &_x2);
line->x_swap = 1;
}
else {
line->x_swap = 0;
}
if (_y1 > _y2) {
sgl_swap(&_y1, &_y2);
line->y_swap = 1;
}
else {
line->y_swap = 0;
}
/* default thinckness is 1 */
obj->coords.x1 = _x1;
obj->coords.y1 = _y1;
obj->coords.x2 = _x2;
obj->coords.y2 = _y2;
obj->border = 2;
sgl_obj_set_dirty(obj);
}

View File

@ -0,0 +1,112 @@
/* source/widgets/sgl_line.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_LINE_H__
#define __SGL_LINE_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief sgl line struct
* @obj: sgl general object
* @color: line color
* @x_swap: x coordinate swap
* @y_swap: y coordinate swap
* @alpha: alpha
*/
typedef struct sgl_line {
sgl_obj_t obj;
sgl_color_t color;
uint8_t x_swap : 4;
uint8_t y_swap : 4;
uint8_t alpha;
}sgl_line_t;
/**
* @brief create a line object
* @param parent parent of the line
* @return line object
*/
sgl_obj_t* sgl_line_create(sgl_obj_t* parent);
/**
* @brief set line color
* @param obj line object
* @param color line color
* @return none
*/
static inline void sgl_line_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_line_t *line = sgl_container_of(obj, sgl_line_t, obj);
line->color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set line alpha
* @param obj line object
* @param alpha line alpha
* @return none
*/
static inline void sgl_line_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
SGL_ASSERT(obj != NULL);
sgl_line_t *line = sgl_container_of(obj, sgl_line_t, obj);
line->alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set line start position
* @param obj line object
* @param x start x position
* @param y start y position
* @return none
*/
void sgl_line_set_pos(sgl_obj_t *obj, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
/**
* @brief set line width
* @param obj line object
* @param width line width
* @return none
*/
static inline void sgl_line_set_width(sgl_obj_t *obj, uint8_t width)
{
SGL_ASSERT(obj != NULL);
obj->border = width << 1;
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_LINE_H__

View File

@ -0,0 +1,286 @@
/* source/widgets/sgl_listview.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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 <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
#include "sgl_listview.h"
#include <sgl.h>
/**
* @brief set listview object style
* @param obj pointer to the object
* @param type style type
* @param value style value
* @return none
*/
void sgl_listview_set_style(sgl_obj_t *obj, sgl_style_type_t type, size_t value)
{
sgl_listview_t *listview = (sgl_listview_t*)obj;
switch((int)type) {
case SGL_STYLE_POS_X:
sgl_obj_set_pos_x(obj, value);
break;
case SGL_STYLE_POS_Y:
sgl_obj_set_pos_y(obj, value);
break;
case SGL_STYLE_SIZE_W:
sgl_obj_set_width(obj, value);
break;
case SGL_STYLE_SIZE_H:
sgl_obj_set_height(obj, value);
break;
case SGL_STYLE_COLOR:
listview->desc.color = sgl_int2color(value);
break;
case SGL_STYLE_RADIUS:
listview->desc.radius = value;
break;
case SGL_STYLE_ALPHA:
listview->desc.alpha = value;
break;
case SGL_STYLE_BORDER_COLOR:
listview->desc.border_color = sgl_int2color(value);
break;
case SGL_STYLE_BORDER_WIDTH:
listview->desc.border = value;
break;
case SGL_STYLE_PIXMAP:
listview->desc.pixmap = (sgl_pixmap_t*)value;
break;
case SGL_STYLE_FONT:
listview->font = (sgl_font_t*)value;
break;
default:
SGL_LOG_WARN("sgl_listview_set_style: unsupported style type %d", type);
break;
}
/* set dirty */
sgl_obj_set_dirty(obj);
}
/**
* @brief get listview object style
* @param obj pointer to the object
* @param type style type
* @return style value
*/
size_t sgl_listview_get_style(sgl_obj_t *obj, sgl_style_type_t type)
{
sgl_listview_t *listview = (sgl_listview_t*)obj;
switch((int)type) {
case SGL_STYLE_POS_X:
return sgl_obj_get_pos_x(obj);
case SGL_STYLE_POS_Y:
return sgl_obj_get_pos_y(obj);
case SGL_STYLE_SIZE_W:
return sgl_obj_get_width(obj);
case SGL_STYLE_SIZE_H:
return sgl_obj_get_height(obj);
case SGL_STYLE_FONT:
return (size_t)listview->font;
default:
SGL_LOG_WARN("sgl_listview_get_style: unsupported style type %d", type);
break;
}
return SGL_STYLE_FAILED;
}
static void sgl_listview_event_cb(sgl_event_t *event)
{
sgl_listview_t *listview = (sgl_listview_t*)event->param;
sgl_obj_t *parent = &listview->obj;
sgl_obj_t *child = NULL;
if(event->type == SGL_EVENT_RELEASED) {
//int diff = item_height + listview->coords_offset;
child = parent->child;
if(listview->coords_offset > 0) {
sgl_obj_for_each_child(child, parent) {
child->coords.y1 -= listview->coords_offset;
child->coords.y2 -= listview->coords_offset;
child->area.y1 -= listview->coords_offset;
child->area.y2 -= listview->coords_offset;
}
listview->coords_offset = 0;
}
// else if(child->coords.y2 < item_height) {
// diff = item_height - child->coords.y2;
// sgl_obj_for_each_child(child, parent) {
// child->coords.y1 += diff;
// child->coords.y2 += diff;
// child->area.y1 += diff;
// child->area.y2 += diff;
// }
// listview->coords_offset = (-diff);
// }
sgl_obj_set_dirty(parent);
}
}
static void sgl_listview_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_listview_t *listview = (sgl_listview_t*)obj;
//int coords_end = 0;
if(evt->type == SGL_EVENT_DRAW_MAIN) {
sgl_draw_rect(surf, &obj->area, &obj->coords, &listview->desc);
}
else if(evt->type == SGL_EVENT_MOVE_UP) {
sgl_listview_set_offset(obj, - evt->distance);
}
else if(evt->type == SGL_EVENT_MOVE_DOWN) {
sgl_listview_set_offset(obj, evt->distance);
}
else if(evt->type == SGL_EVENT_RELEASED) {
}
if(obj->event_fn) {
obj->event_fn(evt);
}
}
/**
* @brief create listview object
* @param parent pointer to the parent object
* @return pointer to the listview object
*/
sgl_obj_t* sgl_listview_create(sgl_obj_t* parent)
{
sgl_listview_t *listview = sgl_malloc(sizeof(sgl_listview_t));
if(listview == NULL) {
SGL_LOG_ERROR("sgl_listview_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(listview, 0, sizeof(sgl_listview_t));
sgl_obj_t *obj = &listview->obj;
sgl_obj_init(&listview->obj, parent);
obj->construct_fn = sgl_listview_construct_cb;
#if CONFIG_SGL_USE_STYLE_UNIFIED_API
obj->set_style = sgl_listview_set_style;
obj->get_style = sgl_listview_get_style;
#endif
sgl_obj_set_movable(obj);
listview->desc.alpha = SGL_ALPHA_MAX;
listview->desc.border = 0;
listview->desc.radius = 0;
listview->font = NULL;
listview->item_count = 0;
listview->item_height = 23;
listview->item_selected = -1;
sgl_obj_set_event_cb(obj, sgl_listview_event_cb, (size_t)listview);
return obj;
}
sgl_obj_t* sgl_listview_add_item(sgl_obj_t *listview, sgl_icon_pixmap_t *icon, const char *text)
{
sgl_listview_t *plistview = (sgl_listview_t *)listview;
sgl_obj_t *new_obj = sgl_button_create(listview);
new_obj->coords.x1 = listview->coords.x1;
new_obj->coords.x2 = listview->coords.x2;
new_obj->coords.y1 = listview->coords.y1 + plistview->item_count * plistview->item_height;
new_obj->coords.y2 = new_obj->coords.y1 + plistview->item_height;
sgl_button_set_style(new_obj, SGL_STYLE_TEXT, (size_t)text);
sgl_button_set_style(new_obj, SGL_STYLE_TEXT_COLOR, SGL_COLOR(SGL_COLOR_BLACK));
sgl_button_set_style(new_obj, SGL_STYLE_ALIGN, SGL_ALIGN_LEFT_MID);
sgl_button_set_style(new_obj, SGL_STYLE_TEXT_X_OFFSET, 10);
if(icon) {
sgl_button_set_style(new_obj, SGL_STYLE_ICON, (size_t)icon);
}
sgl_button_set_style(new_obj, SGL_STYLE_FONT, (size_t)plistview->font);
sgl_button_set_style(new_obj, SGL_STYLE_BORDER_WIDTH, 1);
sgl_button_set_style(new_obj, SGL_STYLE_BORDER_COLOR, SGL_COLOR(SGL_COLOR_BLACK));
sgl_button_set_style(new_obj, SGL_STYLE_COLOR, SGL_COLOR(SGL_COLOR_BLUE));
sgl_obj_set_event_cb(new_obj, sgl_listview_event_cb, (size_t)plistview);
plistview->item_count ++;
return new_obj;
}
void sgl_listview_set_child_style(sgl_obj_t *listview, sgl_style_type_t type, size_t value)
{
sgl_obj_t *child = NULL;
sgl_obj_for_each_child(child, listview) {
sgl_button_set_style(child, type, value);
}
}
void sgl_listview_set_offset(sgl_obj_t *listview, int16_t offset)
{
sgl_listview_t *plistview = (sgl_listview_t *)listview;
plistview->coords_offset += offset;
sgl_obj_t *child = NULL;
sgl_obj_for_each_child(child, listview) {
child->coords.y1 += offset;
child->coords.y2 += offset;
child->area.y1 += offset;
child->area.y2 += offset;
}
}

View File

@ -0,0 +1,88 @@
/* source/widgets/sgl_listview.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: https://sgl-docs.readthedocs.io
*
* 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.
*/
#ifndef __SGL_LISTVIEW_H__
#define __SGL_LISTVIEW_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
/**
* @brief sgl listview
* @obj: sgl general object
* @desc: listview draw description
*/
typedef struct sgl_listview {
sgl_obj_t obj;
sgl_draw_rect_t desc;
sgl_font_t *font;
int16_t item_height;
int16_t item_count;
int16_t item_selected;
int16_t coords_offset;
} sgl_listview_t;
/**
* @brief create listview object
* @param parent pointer to the parent object
* @return pointer to the listview object
*/
sgl_obj_t* sgl_listview_create(sgl_obj_t* parent);
/**
* @brief set listview object style
* @param obj pointer to the object
* @param type style type
* @param value style value
* @return none
*/
void sgl_listview_set_style(sgl_obj_t *obj, sgl_style_type_t type, size_t value);
/**
* @brief get listview object style
* @param obj pointer to the object
* @param type style type
* @return style value
*/
size_t sgl_listview_get_style(sgl_obj_t *obj, sgl_style_type_t type);
sgl_obj_t* sgl_listview_add_item(sgl_obj_t *listview, sgl_icon_pixmap_t *icon, const char *text);
void sgl_listview_set_child_style(sgl_obj_t *listview, sgl_style_type_t type, size_t value);
void sgl_listview_set_offset(sgl_obj_t *listview, int16_t offset);
#endif // !__SGL_LISTVIEW_H__

View File

@ -0,0 +1,54 @@
# source/widgets/lm.cfg
#
# MIT License
#
# Copyright(c) 2023-present All contributors of SGL
# Document reference link: https://sgl-docs.readthedocs.io
#
# 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.
#
SRC += line/sgl_line.c
SRC += rectangle/sgl_rectangle.c
SRC += circle/sgl_circle.c
SRC += ring/sgl_ring.c
SRC += arc/sgl_arc.c
SRC += button/sgl_button.c
SRC += slider/sgl_slider.c
SRC += progress/sgl_progress.c
SRC += label/sgl_label.c
SRC += switch/sgl_switch.c
SRC += msgbox/sgl_msgbox.c
SRC += textline/sgl_textline.c
SRC += textbox/sgl_textbox.c
SRC += checkbox/sgl_checkbox.c
# SRC += listview/sgl_listview.c
SRC += icon/sgl_icon.c
SRC += numberkbd/sgl_numberkbd.c
SRC += keyboard/sgl_keyboard.c
SRC += dropdown/sgl_dropdown.c
SRC += led/sgl_led.c
SRC += 2dball/sgl_2dball.c
SRC += unzip_image/sgl_unzip_image.c
SRC += scroll/sgl_scroll.c
SRC += scope/sgl_scope.c
SRC += ext_img/sgl_ext_img.c
SRC += polygon/sgl_polygon.c
SRC += box/sgl_box.c
SRC += canvas/sgl_canvas.c
SRC += bar/sgl_bar.c
SRC += win/sgl_win.c

View File

@ -0,0 +1,233 @@
/* source/widgets/sgl_msgbox.c
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference: docs directory
*
* 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 "sgl_msgbox.h"
#include <sgl_theme.h>
static void msgbox_draw_text(sgl_surf_t *surf, sgl_area_t *area, sgl_rect_t *coords, const char *text, const sgl_font_t *font, sgl_color_t color, uint8_t alpha, uint8_t y_offset)
{
sgl_pos_t align_pos;
align_pos = sgl_get_text_pos(coords, font, text, 0, SGL_ALIGN_CENTER);
sgl_draw_string(surf, area, align_pos.x, align_pos.y + y_offset, text, color, alpha, font);
}
static void sgl_msgbox_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
const sgl_font_t *font = msgbox->font;
int32_t font_height = sgl_font_get_height(font) + 8;
int16_t border = msgbox->body_desc.border;
uint8_t title_height = msgbox->title_height ? msgbox->title_height : font_height; // title height
uint8_t msg_y_offset = msgbox->text_y_offset; // message text y coords offset
SGL_ASSERT(msgbox->font != NULL);
sgl_color_t tmp_color;
sgl_area_t button_coords = {
.x1 = obj->coords.x1,
.x2 = obj->coords.x2,
.y1 = obj->coords.y2 - font_height,
.y2 = obj->coords.y2
};
sgl_area_t left_coords = {
.x1 = obj->coords.x1 + border,
.x2 = (obj->coords.x1 + obj->coords.x2) / 2 - border / 2,
.y1 = obj->coords.y2 - 2 * font_height,
.y2 = obj->coords.y2 - border,
};
sgl_area_t right_coords = {
.x1 = (obj->coords.x1 + obj->coords.x2) / 2 + border / 2,
.x2 = obj->coords.x2 - border,
.y1 = obj->coords.y2 - 2 * font_height,
.y2 = obj->coords.y2 - border,
};
sgl_area_t title_coords = {
.x1 = obj->coords.x1 + border + 2,
.x2 = obj->coords.x2 - border + 2,
.y1 = obj->coords.y1 + 1,
.y2 = obj->coords.y1 + title_height + border,
};
sgl_area_t text_coords = {
.x1 = obj->coords.x1 + border + 2 + msgbox->text_x_offset,
.x2 = obj->coords.x2 - border - 2,
.y1 = obj->coords.y1 + title_height + border + msg_y_offset,
.y2 = obj->coords.y2 - (font_height + border),
};
if(evt->type == SGL_EVENT_DRAW_MAIN) {
if(msgbox->status & SGL_MSGBOX_STATUS_EXIT) {
sgl_obj_set_destroyed(&msgbox->obj);
}
sgl_draw_rect(surf, &obj->area, &obj->coords, &msgbox->body_desc);
msgbox_draw_text(surf, &obj->area, &title_coords, msgbox->title_text, font, msgbox->title_color, msgbox->body_desc.alpha, 0);
sgl_draw_fill_hline(surf, &obj->area,
obj->coords.y1 + title_height + 4,
obj->coords.x1 + msgbox->body_desc.border,
obj->coords.x2 - msgbox->body_desc.border,
msgbox->body_desc.border,
msgbox->body_desc.border_color,
msgbox->body_desc.alpha
);
sgl_draw_string_mult_line(surf, &text_coords, text_coords.x1, text_coords.y1, msgbox->msg_text, msgbox->msg_color, msgbox->body_desc.alpha, font, msgbox->msg_line_margin);
if(msgbox->status & SGL_MSGBOX_STATUS_LEFT) {
tmp_color = msgbox->lbtn_color;
msgbox->lbtn_color = sgl_color_mixer(msgbox->lbtn_text_color, msgbox->body_desc.color, 128);
}
else if(msgbox->status & SGL_MSGBOX_STATUS_RIGHT) {
tmp_color = msgbox->rbtn_color;
msgbox->rbtn_color = sgl_color_mixer(msgbox->rbtn_text_color, msgbox->body_desc.color, 128);
}
sgl_draw_fill_rect(surf, &button_coords, &left_coords, obj->radius, msgbox->lbtn_color, msgbox->body_desc.alpha);
sgl_draw_fill_rect(surf, &button_coords, &right_coords, obj->radius, msgbox->rbtn_color, msgbox->body_desc.alpha);
msgbox_draw_text(surf, &obj->area, &left_coords, msgbox->lbtn_text, font, msgbox->lbtn_text_color, msgbox->body_desc.alpha, font_height / 2);
msgbox_draw_text(surf, &obj->area, &right_coords, msgbox->rbtn_text, font, msgbox->rbtn_text_color, msgbox->body_desc.alpha, font_height / 2);
if(msgbox->status & SGL_MSGBOX_STATUS_LEFT) {
msgbox->lbtn_color = tmp_color;
}
else if(msgbox->status & SGL_MSGBOX_STATUS_RIGHT) {
msgbox->rbtn_color = tmp_color;
}
}
else if(evt->type == SGL_EVENT_PRESSED) {
if(evt->pos.y > (obj->coords.y2 - font_height - 2) && evt->pos.x < ((obj->coords.x1 + obj->coords.x2) / 2)) {
msgbox->status |= SGL_MSGBOX_STATUS_LEFT;
if (msgbox->exit_btn) {
*msgbox->exit_btn = msgbox->lbtn_text;
}
sgl_obj_update_area(&left_coords);
}
else if(evt->pos.y > (obj->coords.y2 - font_height - 2) && evt->pos.x > ((obj->coords.x1 + obj->coords.x2) / 2)) {
msgbox->status |= SGL_MSGBOX_STATUS_RIGHT;
if (msgbox->exit_btn) {
*msgbox->exit_btn = msgbox->rbtn_text;
}
sgl_obj_update_area(&right_coords);
}
else {
sgl_obj_clear_dirty(obj);
return;
}
}
else if(evt->type == SGL_EVENT_RELEASED) {
if(evt->pos.y > (obj->coords.y2 - font_height - 2) && evt->pos.x < ((obj->coords.x1 + obj->coords.x2) / 2)) {
msgbox->status |= SGL_MSGBOX_STATUS_EXIT;
sgl_obj_set_destroyed(obj);
}
else if(evt->pos.y > (obj->coords.y2 - font_height - 2) && evt->pos.x > ((obj->coords.x1 + obj->coords.x2) / 2)) {
msgbox->status |= SGL_MSGBOX_STATUS_EXIT;
sgl_obj_set_destroyed(obj);
}
else {
sgl_obj_clear_dirty(obj);
return;
}
}
else if (evt->type == SGL_EVENT_OPTION_WALK) {
if (msgbox->status == SGL_MSGBOX_STATUS_NORMAL) {
msgbox->status = SGL_MSGBOX_STATUS_LEFT;
}
else if (msgbox->status == SGL_MSGBOX_STATUS_LEFT) {
msgbox->status = SGL_MSGBOX_STATUS_RIGHT;
if (msgbox->exit_btn) {
*msgbox->exit_btn = msgbox->rbtn_text;
}
}
else if (msgbox->status == SGL_MSGBOX_STATUS_RIGHT) {
msgbox->status = SGL_MSGBOX_STATUS_LEFT;
if (msgbox->exit_btn) {
*msgbox->exit_btn = msgbox->lbtn_text;
}
}
sgl_obj_update_area(&button_coords);
}
else if (evt->type == SGL_EVENT_OPTION_TAP) {
sgl_obj_set_destroyed(obj);
}
}
/**
* @brief create a message box object
* @param parent parent of the message box
* @return message box object
*/
sgl_obj_t* sgl_msgbox_create(sgl_obj_t* parent)
{
sgl_msgbox_t *msgbox = sgl_malloc(sizeof(sgl_msgbox_t));
if(msgbox == NULL) {
SGL_LOG_ERROR("sgl_msgbox_create: malloc failed");
return NULL;
}
/* set object all member to zero */
memset(msgbox, 0, sizeof(sgl_msgbox_t));
sgl_obj_t *obj = &msgbox->obj;
sgl_obj_init(&msgbox->obj, parent);
obj->construct_fn = sgl_msgbox_construct_cb;
sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH);
msgbox->body_desc.alpha = SGL_THEME_ALPHA;
msgbox->body_desc.color = SGL_THEME_COLOR;
msgbox->body_desc.radius = SGL_THEME_RADIUS;
msgbox->body_desc.border = SGL_THEME_BORDER_WIDTH;
msgbox->body_desc.border_color = SGL_THEME_BORDER_COLOR;
msgbox->body_desc.pixmap = NULL;
msgbox->font = sgl_get_system_font();
msgbox->msg_color = SGL_THEME_TEXT_COLOR;
msgbox->title_text = "Message Box";
msgbox->msg_line_margin = 1;
msgbox->msg_text = "NULL";
msgbox->lbtn_color = sgl_color_mixer(SGL_THEME_COLOR, SGL_THEME_TEXT_COLOR, 200);
msgbox->rbtn_color = sgl_color_mixer(SGL_THEME_COLOR, SGL_THEME_TEXT_COLOR, 200);
msgbox->lbtn_text = "YES";
msgbox->rbtn_text = "NO";
msgbox->lbtn_text_color = SGL_THEME_TEXT_COLOR;
msgbox->rbtn_text_color = SGL_THEME_TEXT_COLOR;
msgbox->status = SGL_MSGBOX_STATUS_NORMAL;
msgbox->title_height = 0;
msgbox->text_y_offset = 0;
msgbox->text_x_offset = 0;
msgbox->exit_btn = NULL;
sgl_obj_set_clickable(obj);
return obj;
}

View File

@ -0,0 +1,378 @@
/* source/widgets/sgl_msgbox.h
*
* MIT License
*
* Copyright(c) 2023-present All contributors of SGL
* Document reference link: docs directory
*
* 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.
*/
#ifndef __SGL_MSGBOX_H__
#define __SGL_MSGBOX_H__
#include <sgl_core.h>
#include <sgl_draw.h>
#include <sgl_math.h>
#include <sgl_log.h>
#include <sgl_mm.h>
#include <sgl_cfgfix.h>
#include <string.h>
#define SGL_MSGBOX_STATUS_NORMAL (1 << 7)
#define SGL_MSGBOX_STATUS_LEFT (1 << 0)
#define SGL_MSGBOX_STATUS_RIGHT (1 << 1)
#define SGL_MSGBOX_STATUS_EXIT (1 << 2)
/**
* @brief sgl message box struct
* @obj: sgl general object
* @body_desc: pointer to sgl_draw_rect_t descriptor
*/
typedef struct sgl_msgbox {
sgl_obj_t obj;
sgl_draw_rect_t body_desc;
const sgl_font_t *font;
const char *title_text;
const char *msg_text;
sgl_color_t title_color;
sgl_color_t msg_color;
uint8_t msg_line_margin;
uint8_t status;
sgl_color_t lbtn_text_color;
sgl_color_t rbtn_text_color;
sgl_color_t lbtn_color;
sgl_color_t rbtn_color;
const char *lbtn_text;
const char *rbtn_text;
uint8_t title_height;
uint8_t text_y_offset;
uint8_t text_x_offset;
const char **exit_btn;
}sgl_msgbox_t;
/**
* @brief create a message box object
* @param parent parent of the message box
* @return message box object
*/
sgl_obj_t* sgl_msgbox_create(sgl_obj_t* parent);
/**
* @brief set message box color
* @param obj message box object
* @param color message box color
* @return none
*/
static inline void sgl_msgbox_set_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->body_desc.color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box alpha
* @param obj message box object
* @param alpha message box alpha
* @return none
*/
static inline void sgl_msgbox_set_alpha(sgl_obj_t *obj, uint8_t alpha)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->body_desc.alpha = alpha;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box radius
* @param obj message box object
* @param radius message box radius
* @return none
*/
static inline void sgl_msgbox_set_radius(sgl_obj_t *obj, uint8_t radius)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->body_desc.radius = radius;
sgl_obj_set_radius(obj, radius);
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box border width
* @param obj message box object
* @param width message box border width
* @return none
*/
static inline void sgl_msgbox_set_border_width(sgl_obj_t *obj, uint8_t width)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->body_desc.border = width;
sgl_obj_set_border_width(obj, width);
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box border color
* @param obj message box object
* @param color message box border color
* @return none
*/
static inline void sgl_msgbox_set_border_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->body_desc.border_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box pixmap
* @param obj message box object
* @param pixmap message box pixmap
* @return none
*/
static inline void sgl_msgbox_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->body_desc.pixmap = pixmap;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box all text font
* @param obj message box object
* @param font message box font
* @return none
*/
static inline void sgl_msgbox_set_font(sgl_obj_t *obj, const sgl_font_t *font)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->font = font;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box title text
* @param obj message box object
* @param text message box title text
* @return none
*/
static inline void sgl_msgbox_set_title_text(sgl_obj_t *obj, const char *text)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->title_text = text;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box title text color
* @param obj message box object
* @param color message box title text color
* @return none
*/
static inline void sgl_msgbox_set_title_text_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->title_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box message text
* @param obj message box object
* @param text message box message text
* @return none
*/
static inline void sgl_msgbox_set_msg_text(sgl_obj_t *obj, const char *text)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->msg_text = text;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box message text color
* @param obj message box object
* @param color message box message text color
* @return none
*/
static inline void sgl_msgbox_set_msg_text_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->msg_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box message text line margin
* @param obj message box object
* @param margin message box message text line margin
* @return none
*/
static inline void sgl_msgbox_set_msg_line_margin(sgl_obj_t *obj, uint8_t margin)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->msg_line_margin = margin;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box left button text
* @param obj message box object
* @param text message box left button text
* @return none
*/
static inline void sgl_msgbox_set_left_btn_text(sgl_obj_t *obj, const char *text)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->lbtn_text = text;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box left button text color
* @param obj message box object
* @param color message box left button text color
* @return none
*/
static inline void sgl_msgbox_set_left_btn_text_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->lbtn_text_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box left button color
* @param obj message box object
* @param color message box left button color
* @return none
*/
static inline void sgl_msgbox_set_left_btn_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->lbtn_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box right button text
* @param obj message box object
* @param text message box right button text
* @return none
*/
static inline void sgl_msgbox_set_right_btn_text(sgl_obj_t *obj, const char *text)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->rbtn_text = text;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box right button text color
* @param obj message box object
* @param color message box right button text color
* @return none
*/
static inline void sgl_msgbox_set_right_btn_text_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->rbtn_text_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box right button color
* @param obj message box object
* @param color message box right button color
* @return none
*/
static inline void sgl_msgbox_set_right_btn_color(sgl_obj_t *obj, sgl_color_t color)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->rbtn_color = color;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box exit answer
* @param obj message box object
* @param answer [out] pointer to exit answer
* @return none
* @note the answer will point to the answer btn string when the message box is destroyed
*/
static inline void sgl_msgbox_set_exit_answer(sgl_obj_t *obj, const char **answer)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->exit_btn = answer;
}
/**
* @brief get message box current button text
* @param obj message box object
* @return current current button text
*/
static inline const char* sgl_msgbox_get_current_btn(sgl_obj_t *obj)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
return msgbox->status & SGL_MSGBOX_STATUS_LEFT ? msgbox->lbtn_text : msgbox->rbtn_text;
}
/**
* @brief set message box title height
* @param obj message box object
* @param height title bar height in pixels
* @return none
*/
static inline void sgl_msgbox_set_title_height(sgl_obj_t *obj, uint8_t height)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->title_height = height;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box message text x offset
* @param obj message box object
* @param offset x axis offset for message text
* @return none
*/
static inline void sgl_msgbox_set_msg_x_offset(sgl_obj_t *obj, uint8_t offset)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->text_x_offset = offset;
sgl_obj_set_dirty(obj);
}
/**
* @brief set message box message text y offset
* @param obj message box object
* @param offset y axis offset for message text
* @return none
*/
static inline void sgl_msgbox_set_msg_y_offset(sgl_obj_t *obj, uint8_t offset)
{
sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj);
msgbox->text_y_offset = offset;
sgl_obj_set_dirty(obj);
}
#endif // !__SGL_MSGBOX_H__

Some files were not shown because too many files have changed in this diff Show More