BigW Consortium Gitlab

Commit 791a5a7e by Kiss-Vamosi Gabor

Adding the already exting code

parents
# lvgl
The core of the LittleV Graphical Library
MIT licence
Copyright (c) 2016 Gábor Kiss-Vámosi
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 lv_conf.h
*
*/
#ifndef LV_CONF_H
#define LV_CONF_H
#if 0 /*Remove this to enable the content*/
/*=================
Basic setting
*=================*/
/* Horizontal and vertical resolution of the library.
* Screen resolution multiplied by LV_DOWN_SCALE*/
#define LV_HOR_RES (320 * LV_DOWNSCALE)
#define LV_VER_RES (240 * LV_DOWNSCALE)
/* Buffered rendering: >= LV_DOWNSCALE * LV_HOR_RES or 0 to disable buffering*/
#define LV_VDB_SIZE (LV_HOR_RES * LV_DOWNSCALE * 20)
/* Anti-aliasing with downscaling everything
* 1: disabled
* 2: 2x anti-alias -> half size
* 4: 4x anti-alias -> quarter size */
#define LV_DOWNSCALE 1
#define LV_UPSCALE_FONT 0 /*Scale up fonts to compensate LV_DOWNSCALE*/
#define LV_UPSCALE_MAP 0 /*Scale up maps (e.g. images) elements to compensate LV_DOWNSCALE*/
#define LV_UPSCALE_SYTLE 0 /*Scale up default styles to compensate LV_DOWNSCALE*/
/*=====================
Graphical settings
*=====================*/
/* Horizontal and vertical resolution of the library.
* Screen resolution multiplied by LV_DOWN_SCALE*/
#define LV_HOR_RES (480 * LV_DOWNSCALE)
#define LV_VER_RES (320 * LV_DOWNSCALE)
/* Buffered rendering: >= LV_DOWNSCALE * LV_HOR_RES or 0 to disable buffering*/
#define LV_VDB_SIZE (LV_HOR_RES * LV_DOWNSCALE * 20)
/* Anti-aliasing with downscaling everything
* 1: disabled
* 2: 2x anti-alias -> half size
* 4: 4x anti-alias -> quarter size */
#define LV_DOWNSCALE 2
#define LV_UPSCALE_FONT 0 /*Scale up fonts to compensate LV_DOWNSCALE*/
#define LV_UPSCALE_MAP 0 /*Scale up maps (e.g. images) elements to compensate LV_DOWNSCALE*/
#define LV_UPSCALE_SYTLE 1 /*Scale up default styles to compensate LV_DOWNSCALE*/
#define LV_REFR_PERIOD 50 /*Screen refresh period in milliseconds*/
#define LV_INV_FIFO_SIZE 32 /*The average number of objects on a screen */
/*=================
Misc. setting
*=================*/
/*Display Input settings*/
#define LV_DISPI_READ_PERIOD 50 /*Input device read period milliseconds*/
#define LV_DISPI_TP_MARKER 0 /*Mark the pressed points*/
#define LV_DISPI_DRAG_LIMIT 10 /*Drag threshold in pixels */
#define LV_DISPI_DRAG_THROW 20 /*Drag throw slow-down in [%]. Greater value means faster slow-down */
#define LV_DISPI_LONG_PRESS_TIME 400 /*Long press time in milliseconds*/
/*Coordinates*/
#define LV_CORD_TYPE int16_t /*Coordinate type*/
#define LV_CORD_MAX (32000)
#define LV_CORD_MIN (-32000)
/*Fonts and texts*/
#define USE_FONT_DEJAVU_14 1
#define USE_FONT_DEJAVU_20 1
#define USE_FONT_DEJAVU_30 1
#define USE_FONT_DEJAVU_40 1
#define USE_FONT_DEJAVU_60 1
#define USE_FONT_DEJAVU_80 1
#define LV_FONT_DEFAULT FONT_DEJAVU_40 /*Always set a default font*/
#define LV_TXT_BREAK_CHARS " ,.;-" /*Can break texts on these chars*/
/*lv_obj (base object) settings*/
#define LV_OBJ_FREE_P 1 /*Enable the free pointer attribute*/
#define LV_OBJ_DEF_SCR_COLOR COLOR_WHITE /*Default screen color*/
/*==================
* LV OBJ X USAGE
* ================*/
#define USE_LV_RECT 1
#define USE_LV_LABEL 1
#define USE_LV_BTN 1
#define USE_LV_LINE 1
#define USE_LV_IMG 1
#if USE_LV_IMG != 0
#define LV_IMG_COLOR_TRANSP COLOR_LIME
#endif /*USE_LV_IMG*/
#define USE_LV_PAGE 1
#define USE_LV_LIST 1
/*==================
* LV APP SETTINGS
* =================*/
/*==================
* LV APP X USAGE
* ================*/
#endif /*Remove this to enable the content*/
#endif
/**
* @file lv_draw_img.c
*
*/
/*********************
* INCLUDES
*********************/
#include <lvgl/lv_misc/circ.h>
#include "../../lv_conf.h"
#include <stdio.h>
#include <stdbool.h>
#include "lvgl/lv_misc/text.h"
#include "lv_draw.h"
#include "misc/fs/fsint.h"
#include "misc/math/math_base.h"
#include "lv_draw_rbasic.h"
#include "lv_draw_vbasic.h"
/*********************
* DEFINES
*********************/
#define LINE_WIDTH_CORR_BASE 64
#define LINE_WIDTH_CORR_SHIFT 6
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_draw_rect_main_mid(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa);
static void lv_draw_rect_main_corner(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa);
static void lv_draw_rect_border_straight(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa);
static void lv_draw_rect_border_corner(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa);
static uint16_t lv_draw_rect_radius_corr(uint16_t r, cord_t w, cord_t h);
/**********************
* STATIC VARIABLES
**********************/
#if LV_VDB_SIZE != 0
static void (*fill_fp)(const area_t * cords_p, const area_t * mask_p, color_t color, opa_t opa) = lv_vfill;
static void (*letter_fp)(const point_t * pos_p, const area_t * mask_p, const font_t * font_p, uint8_t letter, color_t color, opa_t opa) = lv_vletter;
static void (*map_fp)(const area_t * cords_p, const area_t * mask_p, const color_t * map_p, opa_t opa, bool transp) = lv_vmap;
#else
static void (*fill_fp)(const area_t * cords_p, const area_t * mask_p, color_t color, opa_t opa) = lv_rfill;
static void (*letter_fp)(const point_t * pos_p, const area_t * mask_p, const font_t * font_p, uint8_t letter, color_t color, opa_t opa) = lv_rletter;
static void (*map_fp)(const area_t * cords_p, const area_t * mask_p, const color_t * map_p, opa_t opa, bool transp) = lv_rmap;
#endif
static lv_rects_t lv_img_no_pic_rects = {
.mcolor = COLOR_BLACK, .gcolor = COLOR_BLACK,
.bcolor = COLOR_RED, .bwidth = 2 * LV_STYLE_MULT, .bopa = 100,
.round = 0, .empty = 0
};
static lv_labels_t lv_img_no_pic_labels = {
.font = LV_FONT_DEFAULT, .color = COLOR_WHITE,
.letter_space = 1 * LV_STYLE_MULT, .line_space = 1 * LV_STYLE_MULT,
.mid = 1, .auto_break = 1
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Draw a rectangle
* @param cords_p the coordinates of the rectangle
* @param mask_p the rectangle will be drawn only in this mask
* @param rects_p pointer to a rectangle style
* @param opa the opacity of the rectangle (0..255)
*/
void lv_draw_rect(const area_t * cords_p, const area_t * mask_p,
const lv_rects_t * rects_p, opa_t opa)
{
if(rects_p->empty == 0){
lv_draw_rect_main_mid(cords_p, mask_p, rects_p, opa);
if(rects_p->round != 0) {
lv_draw_rect_main_corner(cords_p, mask_p, rects_p, opa);
}
}
if(rects_p->bwidth != 0) {
lv_draw_rect_border_straight(cords_p, mask_p, rects_p, opa);
if(rects_p->round != 0) {
lv_draw_rect_border_corner(cords_p, mask_p, rects_p, opa);
}
}
}
/**
* Write a text
* @param cords_p coordinates of the label
* @param mask_p the label will be drawn only in this area
* @param labels_p pointer to a label style
* @param opa opacity of the text (0..255)
* @param txt 0 terminated text to write
*/
void lv_draw_label(const area_t * cords_p,const area_t * mask_p,
const lv_labels_t * labels_p, opa_t opa, const char * txt)
{
const font_t * font_p = font_get(labels_p->font);
cord_t w = area_get_width(cords_p);
cord_t max_w = w;
/*If the auto-break is not enabled the set the max length to very big */
if(labels_p->auto_break == 0) {
max_w = LV_CORD_MAX;
}
/*Init variables for the first line*/
cord_t line_length = 0;
uint32_t line_start = 0;
uint32_t line_end = txt_get_next_line(txt, font_p, labels_p->letter_space, max_w);
point_t pos;
pos.x = cords_p->x1;
pos.y = cords_p->y1;
/*Align the line to middle if enabled*/
if(labels_p->mid != 0) {
line_length = txt_get_length(&txt[line_start], line_end - line_start,
font_p, labels_p->letter_space);
pos.x += (w - line_length) / 2;
}
uint32_t i;
/*Write out all lines*/
while(txt[line_start] != '\0') {
/*Write all letter of a line*/
for(i = line_start; i < line_end; i++) {
letter_fp(&pos, mask_p, font_p, txt[i], labels_p->color, opa);
pos.x += font_get_width(font_p, txt[i]) + labels_p->letter_space;
}
/*Go to next line*/
line_start = line_end;
line_end += txt_get_next_line(&txt[line_start], font_p, labels_p->letter_space, max_w);
pos.x = cords_p->x1;
/*Align to middle*/
if(labels_p->mid != 0) {
line_length = txt_get_length(&txt[line_start], line_end - line_start,
font_p, labels_p->letter_space);
pos.x += (w - line_length) / 2;
}
/*Go the next line position*/
pos.y += font_get_height(font_p);
pos.y += labels_p->line_space;
}
}
/**
* Draw an image
* @param cords_p the coordinates of the image
* @param mask_p the image will be drawn only in this area
* @param map_p pointer to a color_t array which contains the pixels of the image
* @param opa opacity of the image (0..255)
*/
void lv_draw_img(const area_t * cords_p, const area_t * mask_p,
const lv_imgs_t * imgs_p, opa_t opa, const char * fn, const color_t * map_p)
{
if(map_p != NULL) {
map_fp(cords_p, mask_p, map_p, opa, imgs_p->transp_en);
} else if(fn != NULL) {
fs_file_t file;
fs_res_t res = fs_open(&file, fn, FS_MODE_RD);
if(res == FS_RES_OK) {
cord_t row;
color_t buf[LV_HOR_RES];
uint32_t br;
area_t act_area;
uint8_t ds_shift = 0;
uint8_t ds_num = 0;
#if LV_DOWNSCALE <= 1 || LV_UPSCALE_MAP == 0
ds_shift = 0;
ds_num = 1;
#elif LV_DOWNSCALE == 2
ds_shift = 1;
ds_num = 2;
#elif LV_DOWNSCALE == 4
ds_shift = 2;
ds_num = 4;
#else
#error "LV: not supported LV_DOWNSCALE value"
#endif
area_t mask_sub;
bool union_ok;
union_ok = area_union(&mask_sub, mask_p, cords_p);
if(union_ok == false) {
fs_close(&file);
return;
}
uint32_t start_offset = sizeof(lv_img_raw_header_t);
start_offset += (area_get_width(cords_p) >> ds_shift) *
((mask_sub.y1 - cords_p->y1) >> ds_shift) * sizeof(color_t); /*First row*/
start_offset += ((mask_sub.x1 - cords_p->x1) >> ds_shift) * sizeof(color_t); /*First col*/
fs_seek(&file, start_offset);
uint32_t useful_data = (area_get_width(&mask_sub) >> ds_shift)* sizeof(color_t);
uint32_t next_row = (area_get_width(cords_p) >> ds_shift) * sizeof(color_t) - useful_data;
area_cpy(&act_area, &mask_sub);
act_area.y2 = act_area.y1 + ds_num - 1;
uint32_t act_pos;
for(row = mask_sub.y1; row <= mask_sub.y2; row += ds_num) {
res = fs_read(&file, buf, useful_data, &br);
map_fp(&act_area, &mask_sub, buf, opa, imgs_p->transp_en);
fs_tell(&file, &act_pos);
fs_seek(&file, act_pos + next_row);
act_area.y1 += ds_num;
act_area.y2 += ds_num;
}
}
fs_close(&file);
if(res != FS_RES_OK) {
lv_draw_rect(cords_p, mask_p, &lv_img_no_pic_rects, opa);
lv_draw_label(cords_p, mask_p,&lv_img_no_pic_labels, opa, fn);
}
} else {
lv_draw_rect(cords_p, mask_p, &lv_img_no_pic_rects, opa);
lv_draw_label(cords_p, mask_p,&lv_img_no_pic_labels, opa, "No data");
}
}
/**
* Draw a line
* @param p1 first point of the line
* @param p2 second point of the line
* @param mask_pthe line will be drawn only on this area
* @param lines_p pointer to a line style
* @param opa opacity of the line (0..255)
*/
void lv_draw_line(const point_t * p1, const point_t * p2, const area_t * mask_p,
const lv_lines_t * lines_p, opa_t opa)
{
/*Draw circle*//*
point_t c1;
point_t c2;
cord_t ctmp1;
cord_t ctmp2;
area_t tmp_a;
circ_init(&c1, &ctmp1, lines_p->line_width);
cord_t dx = abs(p2->x - p1->x);
cord_t dy = abs(p2->y - p1->y);
uint16_t width;
uint16_t wcor;
opa = OPA_20;
static const uint8_t width_corr_array[] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66,
67, 67, 67, 68, 68, 68, 69, 69, 69, 70, 70, 71, 71, 72, 72, 72, 73, 73, 74,
74, 75, 75, 76, 77, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 83, 84, 84, 85,
86, 86, 87, 88, 88, 89, 90, 91,
};
wcor = (dy * LINE_WIDTH_CORR_BASE) / dx;
width = ((lines_p->line_width) * LV_DOWNSCALE * width_corr_array[wcor]) >> LINE_WIDTH_CORR_SHIFT;
point_t e;
int32_t x_tmp = ((width*dy*dx)/(dx*dx+dy*dy));
e.x = p2->x + x_tmp;
e.y = p2->y - (x_tmp * dx)/dy;
area_t e_area;
e_area.x1 = e.x-3;
e_area.x2 = e.x+3;
e_area.y1 = e.y-3;
e_area.y2 = e.y+3;
lv_vfill(&e_area, mask_p, COLOR_GREEN, OPA_40);
color_t rnd_clr = {{130, 43, 99}};
uint16_t cnt = 0;
while(circ_cont(&c1)) {
area_set(&tmp_a, CIRC_OCT1_X(c1)+p2->x, CIRC_OCT1_Y(c1)+p2->y, CIRC_OCT1_X(c1)+p2->x, CIRC_OCT1_Y(c1)+p2->y);
lv_vfill(&tmp_a, mask_p, COLOR_BLUE, OPA_COVER);
area_set(&tmp_a, CIRC_OCT2_X(c1)+p2->x, CIRC_OCT2_Y(c1)+p2->y, CIRC_OCT2_X(c1)+p2->x, CIRC_OCT2_Y(c1)+p2->y);
lv_vfill(&tmp_a, mask_p, lines_p->color, opa);
area_set(&tmp_a, CIRC_OCT3_X(c1)+p2->x, CIRC_OCT3_Y(c1)+p2->y, CIRC_OCT3_X(c1)+p2->x, CIRC_OCT3_Y(c1)+p2->y);
lv_vfill(&tmp_a, mask_p, lines_p->color, opa);
area_set(&tmp_a, CIRC_OCT4_X(c1)+p2->x, CIRC_OCT4_Y(c1)+p2->y, CIRC_OCT4_X(c1)+p2->x, CIRC_OCT4_Y(c1)+p2->y);
lv_vfill(&tmp_a, mask_p, lines_p->color, opa);
area_set(&tmp_a, CIRC_OCT5_X(c1)+p2->x, CIRC_OCT5_Y(c1)+p2->y, CIRC_OCT5_X(c1)+p2->x, CIRC_OCT5_Y(c1)+p2->y);
lv_vfill(&tmp_a, mask_p, lines_p->color, opa);
area_set(&tmp_a, CIRC_OCT6_X(c1)+p2->x, CIRC_OCT6_Y(c1)+p2->y, CIRC_OCT6_X(c1)+p2->x, CIRC_OCT6_Y(c1)+p2->y);
lv_vfill(&tmp_a, mask_p, lines_p->color, opa);
area_set(&tmp_a, CIRC_OCT7_X(c1)+p2->x, CIRC_OCT7_Y(c1)+p2->y, CIRC_OCT7_X(c1)+p2->x, CIRC_OCT7_Y(c1)+p2->y);
lv_vfill(&tmp_a, mask_p, COLOR_PURPLE, OPA_COVER);
area_set(&tmp_a, CIRC_OCT8_X(c1)+p2->x, CIRC_OCT8_Y(c1)+p2->y, CIRC_OCT8_X(c1)+p2->x, CIRC_OCT8_Y(c1)+p2->y);
lv_vfill(&tmp_a, mask_p, lines_p->color, opa);
cord_t err = (dx > dy ? dx : -dy) / 2;
cord_t e2;
point_t act_point;
act_point.x = p1->x;
act_point.y = p1->y;
rnd_clr.full += 0x238993;
while(1){
//if(c1.y > 4) break;
area_t act_area;
*/
/*if(act_point.x < p2->x + CIRC_OCT8_X(c1))
{
act_area.x1 = act_point.x;
act_area.x2 = act_point.x;
act_area.y1 = act_point.y - ((CIRC_OCT8_X(c1)*dy) - (CIRC_OCT8_Y(c1)*dx)) / (dx);
act_area.y2 = act_point.y - ((CIRC_OCT8_X(c1)*dy) - (CIRC_OCT8_Y(c1)*dx)) / (dx);// (dy * c1.x)/dx + CIRC_OCT8_Y(c1);
lv_vfill(&act_area, mask_p, COLOR_RED, OPA_50);
}*/
/*
if(act_point.x < p2->x + CIRC_OCT1_X(c1)) {
act_area.x1 = act_point.x;
act_area.x2 = act_point.x;
act_area.y1 = act_point.y - (dy * c1.x)/dx + CIRC_OCT1_Y(c1);
act_area.y2 = act_point.y - (dy * c1.x)/dx + CIRC_OCT1_Y(c1);
lv_vfill(&act_area, mask_p, COLOR_RED, OPA_50);
}
if(act_point.x < p2->x + CIRC_OCT2_X(c1)) {
act_area.x1 = act_point.x;
act_area.x2 = act_point.x;
act_area.y1 = act_point.y - (dy * CIRC_OCT2_X(c1))/dx + CIRC_OCT2_Y(c1);
act_area.y2 = act_point.y - (dy * CIRC_OCT2_X(c1))/dx + CIRC_OCT2_Y(c1);
lv_vfill(&act_area, mask_p, COLOR_RED, OPA_50);
}
if(act_point.x < p2->x + CIRC_OCT3_X(c1)) {
act_area.x1 = act_point.x;
act_area.x2 = act_point.x;
act_area.y1 = act_point.y - (dy * CIRC_OCT3_X(c1))/dx + CIRC_OCT3_Y(c1);
act_area.y2 = act_point.y - (dy * CIRC_OCT3_X(c1))/dx + CIRC_OCT3_Y(c1);
lv_vfill(&act_area, mask_p, COLOR_RED, OPA_50);
}
*//*
if(e.x > p2->x && e.x < p2->x + lines_p->line_width / 2 &&
act_point.x < p2->x + CIRC_OCT7_X(c1))
{
act_area.x1 = act_point.x;
act_area.x2 = act_point.x;
act_area.y1 = act_point.y - (dy * CIRC_OCT7_X(c1))/dx + CIRC_OCT7_Y(c1);
act_area.y2 = act_area.y1;
lv_vfill(&act_area, mask_p, COLOR_RED, OPA_50);
}*/
/*
if(act_point.x < p2->x + CIRC_OCT7_X(c1)) {
act_area.x1 = act_point.x;
act_area.x2 = act_point.x;
act_area.y1 = act_point.y - (dy * CIRC_OCT7_X(c1))/dx + CIRC_OCT7_Y(c1);
act_area.y2 = act_point.y - (dy * CIRC_OCT7_X(c1))/dx + CIRC_OCT7_Y(c1);
lv_vfill(&act_area, mask_p, COLOR_RED, OPA_50);
}
*/
//printf("hor x1:%d, y1:%d, x2:%d, y2:%d\n", act_area.x1, act_area.y1, act_area.x2, act_area.y2);
/*if (act_point.x == p2->x + c1.x)
{
printf("line end x%d, y%d\n", act_area.x1, act_area.y1);
cnt++;
if(cnt == 11) {
cnt++;
cnt--;
}
break;
}
e2 = err;
if (e2 >-dx) {
err -= dy;
act_point.x ++;
}
if (e2 < dy) {
err += dx;
act_point.y ++;
}
}
circ_next(&c1, &ctmp1);
}
return;*/
if(lines_p->width == 0) return;
if(p1->x == p2->x && p1->y == p2->y) return;
cord_t dx = abs(p2->x - p1->x);
cord_t sx = p1->x < p2->x ? 1 : -1;
cord_t dy = abs(p2->y - p1->y);
cord_t sy = p1->y < p2->y ? 1 : -1;
cord_t err = (dx > dy ? dx : -dy) / 2;
cord_t e2;
bool hor = dx > dy ? true : false; /*Rather horizontal or vertical*/
cord_t last_x = p1->x;
cord_t last_y = p1->y;
point_t act_point;
act_point.x = p1->x;
act_point.y = p1->y;
uint16_t width;
uint16_t wcor;
uint16_t width_half;
uint16_t width_1;
static const uint8_t width_corr_array[] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66,
67, 67, 67, 68, 68, 68, 69, 69, 69, 70, 70, 71, 71, 72, 72, 72, 73, 73, 74,
74, 75, 75, 76, 77, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 83, 84, 84, 85,
86, 86, 87, 88, 88, 89, 90, 91,
};
if(hor == false) {
wcor = (dx * LINE_WIDTH_CORR_BASE) / dy;
} else {
wcor = (dy * LINE_WIDTH_CORR_BASE) / dx;
}
/*Make the correction on lie width*/
width = ((lines_p->width - 1) * width_corr_array[wcor]) >> LINE_WIDTH_CORR_SHIFT;
width_half = width >> 1;
width_1 = width & 0x1 ? 1 : 0;
while(1){
if(hor == true && last_y != act_point.y) {
area_t act_area;
area_t draw_area;
act_area.x1 = last_x;
act_area.x2 = act_point.x - sx;
act_area.y1 = last_y - width_half ;
act_area.y2 = act_point.y - sy + width_half + width_1;
last_y = act_point.y;
last_x = act_point.x;
draw_area.x1 = min(act_area.x1, act_area.x2);
draw_area.x2 = max(act_area.x1, act_area.x2);
draw_area.y1 = min(act_area.y1, act_area.y2);
draw_area.y2 = max(act_area.y1, act_area.y2);
fill_fp(&draw_area, mask_p, lines_p->color, opa);
}
if (hor == false && last_x != act_point.x) {
area_t act_area;
area_t draw_area;
act_area.x1 = last_x - width_half;
act_area.x2 = act_point.x - sx + width_half + width_1;
act_area.y1 = last_y ;
act_area.y2 = act_point.y - sy;
last_y = act_point.y;
last_x = act_point.x;
draw_area.x1 = min(act_area.x1, act_area.x2);
draw_area.x2 = max(act_area.x1, act_area.x2);
draw_area.y1 = min(act_area.y1, act_area.y2);
draw_area.y2 = max(act_area.y1, act_area.y2);
fill_fp(&draw_area, mask_p, lines_p->color, opa);
}
/*Calc. the next point of the line*/
if (act_point.x == p2->x && act_point.y == p2->y) break;
e2 = err;
if (e2 >-dx) {
err -= dy;
act_point.x += sx;
}
if (e2 < dy) {
err += dx;
act_point.y += sy;
}
}
/*Draw the last part of the line*/
if(hor == true) {
area_t act_area;
area_t draw_area;
act_area.x1 = last_x;
act_area.x2 = act_point.x;
act_area.y1 = last_y - width_half ;
act_area.y2 = act_point.y + width_half + width_1;
draw_area.x1 = min(act_area.x1, act_area.x2);
draw_area.x2 = max(act_area.x1, act_area.x2);
draw_area.y1 = min(act_area.y1, act_area.y2);
draw_area.y2 = max(act_area.y1, act_area.y2);
fill_fp(&draw_area, mask_p, lines_p->color, opa);
}
if (hor == false) {
area_t act_area;
area_t draw_area;
act_area.x1 = last_x - width_half;
act_area.x2 = act_point.x + width_half + width_1;
act_area.y1 = last_y;
act_area.y2 = act_point.y;
draw_area.x1 = min(act_area.x1, act_area.x2);
draw_area.x2 = max(act_area.x1, act_area.x2);
draw_area.y1 = min(act_area.y1, act_area.y2);
draw_area.y2 = max(act_area.y1, act_area.y2);
fill_fp(&draw_area, mask_p, lines_p->color, opa);
}
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Draw the middle part (rectangular) of a rectangle
* @param cords_p the coordinates of the original rectangle
* @param mask_p the rectangle will be drawn only on this area
* @param rects_p pointer to a rectangle style
* @param opa opacity of the rectangle (0..255)
*/
static void lv_draw_rect_main_mid(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa)
{
uint16_t radius = rects_p->round;
color_t main_color = rects_p->mcolor;
color_t grad_color = rects_p->gcolor;
uint8_t mix;
cord_t height = area_get_height(cords_p);
cord_t width = area_get_width(cords_p);
radius = lv_draw_rect_radius_corr(radius, width, height);
/*If the radius is too big then there is no body*/
if(radius > height / 2) return;
area_t work_area;
work_area.x1 = cords_p->x1;
work_area.x2 = cords_p->x2;
if(main_color.full == grad_color.full) {
work_area.y1 = cords_p->y1 + radius;
work_area.y2 = cords_p->y2 - radius;
fill_fp(&work_area, mask_p, main_color, opa);
} else {
cord_t row;
cord_t row_start = cords_p->y1 + radius;
cord_t row_end = cords_p->y2 - radius;
color_t act_color;
if(row_start < 0) row_start = 0;
for(row = row_start ;
row <= row_end;
row ++)
{
work_area.y1 = row;
work_area.y2 = row;
mix = (uint32_t)((uint32_t)(cords_p->y2 - work_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&work_area, mask_p, act_color, opa);
}
}
}
/**
* Draw the top and bottom parts (corners) of a rectangle
* @param cords_p the coordinates of the original rectangle
* @param mask_p the rectangle will be drawn only on this area
* @param rects_p pointer to a rectangle style
* @param opa opacity of the rectangle (0..255)
*/
static void lv_draw_rect_main_corner(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa)
{
uint16_t radius = rects_p->round;
color_t main_color = rects_p->mcolor;
color_t grad_color = rects_p->gcolor;
color_t act_color;
uint8_t mix;
cord_t height = area_get_height(cords_p);
cord_t width = area_get_width(cords_p);
radius = lv_draw_rect_radius_corr(radius, width, height);
point_t lt_origo; /*Left Top origo*/
point_t lb_origo; /*Left Bottom origo*/
point_t rt_origo; /*Right Top origo*/
point_t rb_origo; /*Left Bottom origo*/
lt_origo.x = cords_p->x1 + radius;
lt_origo.y = cords_p->y1 + radius;
lb_origo.x = cords_p->x1 + radius;
lb_origo.y = cords_p->y2 - radius;
rt_origo.x = cords_p->x2 - radius;
rt_origo.y = cords_p->y1 + radius;
rb_origo.x = cords_p->x2 - radius;
rb_origo.y = cords_p->y2 - radius;
area_t edge_top_area;
area_t mid_top_area;
area_t mid_bot_area;
area_t edge_bot_area;
point_t cir;
cord_t cir_tmp;
circ_init(&cir, &cir_tmp, radius);
/*Init the areas*/
area_set(&mid_bot_area, lb_origo.x + CIRC_OCT4_X(cir),
lb_origo.y + CIRC_OCT4_Y(cir),
rb_origo.x + CIRC_OCT1_X(cir),
rb_origo.y + CIRC_OCT1_Y(cir));
area_set(&edge_bot_area, lb_origo.x + CIRC_OCT3_X(cir),
lb_origo.y + CIRC_OCT3_Y(cir),
rb_origo.x + CIRC_OCT2_X(cir),
rb_origo.y + CIRC_OCT2_Y(cir));
area_set(&mid_top_area, lt_origo.x + CIRC_OCT5_X(cir),
lt_origo.y + CIRC_OCT5_Y(cir),
rt_origo.x + CIRC_OCT8_X(cir),
rt_origo.y + CIRC_OCT8_Y(cir));
area_set(&edge_top_area, lt_origo.x + CIRC_OCT6_X(cir),
lt_origo.y + CIRC_OCT6_Y(cir),
rt_origo.x + CIRC_OCT7_X(cir),
rt_origo.y + CIRC_OCT7_Y(cir));
while(circ_cont(&cir)) {
uint8_t edge_top_refr = 0;
uint8_t mid_top_refr = 0;
uint8_t mid_bot_refr = 0;
uint8_t edge_bot_refr = 0;
/*If a new row coming draw the previous
* The x coordinate can grow on the same y so wait for the last x*/
if(mid_bot_area.y1 != CIRC_OCT4_Y(cir) + lb_origo.y ) {
mid_bot_refr = 1;
}
if(edge_bot_area.y1 != CIRC_OCT2_Y(cir) + lb_origo.y) {
edge_bot_refr = 1;
}
if(mid_top_area.y1 != CIRC_OCT8_Y(cir) + lt_origo.y) {
mid_top_refr = 1;
}
if(edge_top_area.y1 != CIRC_OCT7_Y(cir) + lt_origo.y) {
edge_top_refr = 1;
}
/* Do not refresh the first row in the middle
* because the body drawer makes it*/
if(mid_bot_area.y1 == cords_p->y2 - radius){
mid_bot_refr = 0;
}
if(mid_top_area.y1 == cords_p->y1 + radius){
mid_top_refr = 0;
}
/*Draw the areas which are not disabled*/
if(edge_top_refr != 0){
mix = (uint32_t)((uint32_t)(cords_p->y2 - edge_top_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&edge_top_area, mask_p, act_color, opa);
}
if(mid_top_refr != 0) {
mix = (uint32_t)((uint32_t)(cords_p->y2 - mid_top_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&mid_top_area, mask_p, act_color, opa);
}
if(mid_bot_refr != 0) {
mix = (uint32_t)((uint32_t)(cords_p->y2 - mid_bot_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&mid_bot_area, mask_p, act_color, opa);
}
if(edge_bot_refr != 0) {
mix = (uint32_t)((uint32_t)(cords_p->y2 - edge_bot_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&edge_bot_area, mask_p, act_color, opa);
}
/*Save the current coordinates*/
area_set(&mid_bot_area, lb_origo.x + CIRC_OCT4_X(cir),
lb_origo.y + CIRC_OCT4_Y(cir),
rb_origo.x + CIRC_OCT1_X(cir),
rb_origo.y + CIRC_OCT1_Y(cir));
area_set(&edge_bot_area, lb_origo.x + CIRC_OCT3_X(cir),
lb_origo.y + CIRC_OCT3_Y(cir),
rb_origo.x + CIRC_OCT2_X(cir),
rb_origo.y + CIRC_OCT2_Y(cir));
area_set(&mid_top_area, lt_origo.x + CIRC_OCT5_X(cir),
lt_origo.y + CIRC_OCT5_Y(cir),
rt_origo.x + CIRC_OCT8_X(cir),
rt_origo.y + CIRC_OCT8_Y(cir));
area_set(&edge_top_area, lt_origo.x + CIRC_OCT6_X(cir),
lt_origo.y + CIRC_OCT6_Y(cir),
rt_origo.x + CIRC_OCT7_X(cir),
rt_origo.y + CIRC_OCT7_Y(cir));
circ_next(&cir, &cir_tmp);
}
mix = (uint32_t)((uint32_t)(cords_p->y2 - edge_top_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&edge_top_area, mask_p, act_color, opa);
if(edge_top_area.y1 != mid_top_area.y1) {
mix = (uint32_t)((uint32_t)(cords_p->y2 - mid_top_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&mid_top_area, mask_p, act_color, opa);
}
mix = (uint32_t)((uint32_t)(cords_p->y2 - mid_bot_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&mid_bot_area, mask_p, act_color, opa);
if(edge_bot_area.y1 != mid_bot_area.y1) {
mix = (uint32_t)((uint32_t)(cords_p->y2 - edge_bot_area.y1) * 255) / height;
act_color = color_mix(main_color, grad_color, mix);
fill_fp(&edge_bot_area, mask_p, act_color, opa);
}
}
/**
* Draw the straight parts of a rectangle border
* @param cords_p the coordinates of the original rectangle
* @param mask_p the rectangle will be drawn only on this area
* @param rects_p pointer to a rectangle style
* @param opa opacity of the rectangle (0..255)
*/
static void lv_draw_rect_border_straight(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa)
{
uint16_t radius = rects_p->round;
cord_t width = area_get_width(cords_p);
cord_t height = area_get_height(cords_p);
uint16_t b_width = rects_p->bwidth;
opa_t b_opa = (uint16_t)((uint16_t) opa * rects_p->bopa) / 100;
area_t work_area;
cord_t length_corr = 0;
cord_t corner_size = 0;
/*the 0 px border width drawn as 1 px, so decrement the b_width*/
b_width--;
radius = lv_draw_rect_radius_corr(radius, width, height);
if(radius < b_width) {
length_corr = b_width - radius;
corner_size = b_width;
} else {
corner_size = radius;
}
/* Modify the corner_size if corner is drawn */
corner_size ++;
color_t b_color = rects_p->bcolor;
/*Left border*/
work_area.x1 = cords_p->x1;
work_area.x2 = work_area.x1 + b_width;
work_area.y1 = cords_p->y1 + corner_size;
work_area.y2 = cords_p->y2 - corner_size;
fill_fp(&work_area, mask_p, b_color, b_opa);
/*Right border*/
work_area.x2 = cords_p->x2;
work_area.x1 = work_area.x2 - b_width;
fill_fp(&work_area, mask_p, b_color, b_opa);
/*Upper border*/
work_area.x1 = cords_p->x1 + corner_size - length_corr;
work_area.x2 = cords_p->x2 - corner_size + length_corr;
work_area.y1 = cords_p->y1;
work_area.y2 = cords_p->y1 + b_width;
fill_fp(&work_area, mask_p, b_color, b_opa);
/*Lower border*/
work_area.y2 = cords_p->y2;
work_area.y1 = work_area.y2 - b_width;
fill_fp(&work_area, mask_p, b_color, b_opa);
/*Draw the a remaining rectangles if the radius is smaller then b_width */
if(length_corr != 0) {
work_area.x1 = cords_p->x1;
work_area.x2 = cords_p->x1 + radius;
work_area.y1 = cords_p->y1 + radius + 1;
work_area.y2 = cords_p->y1 + b_width;
fill_fp(&work_area, mask_p, b_color, b_opa);
work_area.x1 = cords_p->x2 - radius;
work_area.x2 = cords_p->x2;
work_area.y1 = cords_p->y1 + radius + 1;
work_area.y2 = cords_p->y1 + b_width;
fill_fp(&work_area, mask_p, b_color, b_opa);
work_area.x1 = cords_p->x1;
work_area.x2 = cords_p->x1 + radius;
work_area.y1 = cords_p->y2 - b_width;
work_area.y2 = cords_p->y2 - radius - 1;
fill_fp(&work_area, mask_p, b_color, b_opa);
work_area.x1 = cords_p->x2 - radius;
work_area.x2 = cords_p->x2;
work_area.y1 = cords_p->y2 - b_width;
work_area.y2 = cords_p->y2 - radius - 1;
fill_fp(&work_area, mask_p, b_color, b_opa);
}
/*If radius == 0 one px on the corners are not drawn*/
if(radius == 0) {
work_area.x1 = cords_p->x1;
work_area.x2 = cords_p->x1;
work_area.y1 = cords_p->y1;
work_area.y2 = cords_p->y1;
fill_fp(&work_area, mask_p, b_color, b_opa);
work_area.x1 = cords_p->x2;
work_area.x2 = cords_p->x2;
work_area.y1 = cords_p->y1;
work_area.y2 = cords_p->y1;
fill_fp(&work_area, mask_p, b_color, b_opa);
work_area.x1 = cords_p->x1;
work_area.x2 = cords_p->x1;
work_area.y1 = cords_p->y2;
work_area.y2 = cords_p->y2;
fill_fp(&work_area, mask_p, b_color, b_opa);
work_area.x1 = cords_p->x2;
work_area.x2 = cords_p->x2;
work_area.y1 = cords_p->y2;
work_area.y2 = cords_p->y2;
fill_fp(&work_area, mask_p, b_color, b_opa);
}
}
/**
* Draw the corners of a rectangle border
* @param cords_p the coordinates of the original rectangle
* @param mask_p the rectangle will be drawn only on this area
* @param rects_p pointer to a rectangle style
* @param opa opacity of the rectangle (0..255)
*/
static void lv_draw_rect_border_corner(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa)
{
uint16_t radius = rects_p->round;
uint16_t b_width = rects_p->bwidth;
color_t b_color = rects_p->bcolor;
opa_t b_opa = (uint16_t)((uint16_t) opa * rects_p->bopa ) / 100;
/*0 px border width drawn as 1 px, so decrement the b_width*/
b_width--;
cord_t width = area_get_width(cords_p);
cord_t height = area_get_height(cords_p);
radius = lv_draw_rect_radius_corr(radius, width, height);
point_t lt_origo; /*Left Top origo*/
point_t lb_origo; /*Left Bottom origo*/
point_t rt_origo; /*Right Top origo*/
point_t rb_origo; /*Left Bottom origo*/
lt_origo.x = cords_p->x1 + radius;
lt_origo.y = cords_p->y1 + radius;
lb_origo.x = cords_p->x1 + radius;
lb_origo.y = cords_p->y2 - radius;
rt_origo.x = cords_p->x2 - radius;
rt_origo.y = cords_p->y1 + radius;
rb_origo.x = cords_p->x2 - radius;
rb_origo.y = cords_p->y2 - radius;
point_t cir_out;
cord_t tmp_out;
circ_init(&cir_out, &tmp_out, radius);
point_t cir_in;
cord_t tmp_in;
cord_t radius_in = radius - b_width;
if(radius_in < 0){
radius_in = 0;
}
circ_init(&cir_in, &tmp_in, radius_in);
area_t circ_area;
cord_t act_w1;
cord_t act_w2;
while( cir_out.y <= cir_out.x) {
/*Calculate the actual width to avoid overwriting pixels*/
if(cir_in.y < cir_in.x) {
act_w1 = cir_out.x - cir_in.x;
act_w2 = act_w1;
} else {
act_w1 = cir_out.x - cir_out.y;
act_w2 = act_w1 - 1;
}
/*Draw the octets to the right bottom corner*/
circ_area.x1 = rb_origo.x + CIRC_OCT1_X(cir_out) - act_w2;
circ_area.x2 = rb_origo.x + CIRC_OCT1_X(cir_out);
circ_area.y1 = rb_origo.y + CIRC_OCT1_Y(cir_out);
circ_area.y2 = rb_origo.y + CIRC_OCT1_Y(cir_out);
fill_fp(&circ_area, mask_p, b_color, b_opa);
circ_area.x1 = rb_origo.x + CIRC_OCT2_X(cir_out);
circ_area.x2 = rb_origo.x + CIRC_OCT2_X(cir_out);
circ_area.y1 = rb_origo.y + CIRC_OCT2_Y(cir_out)- act_w1;
circ_area.y2 = rb_origo.y + CIRC_OCT2_Y(cir_out);
fill_fp(&circ_area, mask_p, b_color, b_opa);
/*Draw the octets to the left bottom corner*/
circ_area.x1 = lb_origo.x + CIRC_OCT3_X(cir_out);
circ_area.x2 = lb_origo.x + CIRC_OCT3_X(cir_out);
circ_area.y1 = lb_origo.y + CIRC_OCT3_Y(cir_out) - act_w2;
circ_area.y2 = lb_origo.y + CIRC_OCT3_Y(cir_out);
fill_fp(&circ_area, mask_p, b_color, b_opa);
circ_area.x1 = lb_origo.x + CIRC_OCT4_X(cir_out);
circ_area.x2 = lb_origo.x + CIRC_OCT4_X(cir_out) + act_w1;
circ_area.y1 = lb_origo.y + CIRC_OCT4_Y(cir_out);
circ_area.y2 = lb_origo.y + CIRC_OCT4_Y(cir_out);
fill_fp(&circ_area, mask_p, b_color, b_opa);
/*Draw the octets to the left top corner*/
/*Don't draw if the lines are common in the middle*/
if(lb_origo.y + CIRC_OCT4_Y(cir_out) > lt_origo.y + CIRC_OCT5_Y(cir_out)) {
circ_area.x1 = lt_origo.x + CIRC_OCT5_X(cir_out);
circ_area.x2 = lt_origo.x + CIRC_OCT5_X(cir_out) + act_w2;
circ_area.y1 = lt_origo.y + CIRC_OCT5_Y(cir_out);
circ_area.y2 = lt_origo.y + CIRC_OCT5_Y(cir_out);
fill_fp(&circ_area, mask_p, b_color, b_opa);
}
circ_area.x1 = lt_origo.x + CIRC_OCT6_X(cir_out);
circ_area.x2 = lt_origo.x + CIRC_OCT6_X(cir_out);
circ_area.y1 = lt_origo.y + CIRC_OCT6_Y(cir_out);
circ_area.y2 = lt_origo.y + CIRC_OCT6_Y(cir_out) + act_w1;
fill_fp(&circ_area, mask_p, b_color, b_opa);
/*Draw the octets to the right top corner*/
circ_area.x1 = rt_origo.x + CIRC_OCT7_X(cir_out);
circ_area.x2 = rt_origo.x + CIRC_OCT7_X(cir_out);
circ_area.y1 = rt_origo.y + CIRC_OCT7_Y(cir_out);
circ_area.y2 = rt_origo.y + CIRC_OCT7_Y(cir_out) + act_w2;
fill_fp(&circ_area, mask_p, b_color, b_opa);
/*Don't draw if the lines are common in the middle*/
if(rb_origo.y + CIRC_OCT1_Y(cir_out) > rt_origo.y + CIRC_OCT8_Y(cir_out)) {
circ_area.x1 = rt_origo.x + CIRC_OCT8_X(cir_out) - act_w1;
circ_area.x2 = rt_origo.x + CIRC_OCT8_X(cir_out);
circ_area.y1 = rt_origo.y + CIRC_OCT8_Y(cir_out);
circ_area.y2 = rt_origo.y + CIRC_OCT8_Y(cir_out);
fill_fp(&circ_area, mask_p, b_color, b_opa);
}
circ_next(&cir_out, &tmp_out);
/*The internal circle will be ready faster
* so check it! */
if(cir_in.y < cir_in.x) {
circ_next(&cir_in, &tmp_in);
}
}
}
static uint16_t lv_draw_rect_radius_corr(uint16_t r, cord_t w, cord_t h)
{
if(r >= (w >> 1)){
r = (w >> 1);
if(r != 0) r--;
}
if(r >= (h >> 1)) {
r = (h >> 1);
if(r != 0) r--;
}
return r;
}
/**
* @file lv_draw_img.h
*
*/
#ifndef LV_DRAW_H
#define LV_DRAW_H
/*********************
* INCLUDES
*********************/
#include "../lv_objx/lv_btn.h"
#include "../lv_objx/lv_rect.h"
#include "../lv_objx/lv_line.h"
#include "../lv_objx/lv_img.h"
#include "../lv_objx/lv_label.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_rect(const area_t * cords_p, const area_t * mask_p,
const lv_rects_t * rects_p, opa_t opa);
void lv_draw_label(const area_t * cords_p,const area_t * mask_p,
const lv_labels_t * labels_p, opa_t opa, const char * txt);
void lv_draw_line(const point_t * p1, const point_t * p2, const area_t * mask_p,
const lv_lines_t * lines_p, opa_t opa);
void lv_draw_img(const area_t * cords_p, const area_t * mask_p,
const lv_imgs_t * imgs_p, opa_t opa, const char * fn, const color_t * map_p);
/**********************
* MACROS
**********************/
#endif
/**
* @file lv_draw_rbasic.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_rbasic.h"
#include "lv_conf.h"
#include "hal/disp/disp.h"
#include "../lv_misc/font.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_rpx(cord_t x, cord_t y, const area_t * mask_p, color_t color);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Fill an area on the display
* @param cords_p coordinates of the area to fill
* @param mask_p fill only o this mask
* @param color fill color
* @param opa opacity (ignored, only for compatibility with lv_vfill)
*/
void lv_rfill(const area_t * cords_p, const area_t * mask_p,
color_t color, opa_t opa)
{
area_t masked_area;
bool union_ok = true;
if(mask_p != NULL) {
union_ok = area_union(&masked_area, cords_p, mask_p);
} else {
area_t scr_area;
area_set(&scr_area, 0, 0, LV_HOR_RES - 1, LV_VER_RES - 1);
union_ok = area_union(&masked_area, cords_p, &scr_area);
}
if(union_ok != false){
disp_area(DISP_ID_ALL, masked_area.x1, masked_area.y1, masked_area.x2, masked_area.y2);
disp_fill(DISP_ID_ALL, color);
}
}
/**
* Draw a letter to the display
* @param pos_p left-top coordinate of the latter
* @param mask_p the letter will be drawn only on this area
* @param font_p pointer to font
* @param letter a letter to draw
* @param color color of letter
* @param opa opacity of letter (ignored, only for compatibility with lv_vletter)
*/
void lv_rletter(const point_t * pos_p, const area_t * mask_p,
const font_t * font_p, uint8_t letter,
color_t color, opa_t opa)
{
uint8_t w = font_get_width(font_p, letter);
const uint8_t * bitmap_p = font_get_bitmap(font_p, letter);
uint8_t col, col_sub, row;
for(row = 0; row < font_p->height_row; row ++) {
for(col = 0, col_sub = 7; col < w; col ++, col_sub--) {
if(*bitmap_p & (1 << col_sub)) {
lv_rpx(pos_p->x + col, pos_p->y + row, mask_p, color);
}
if(col_sub == 0) {
bitmap_p++;
col_sub = 8;
}
}
/*Correction if the letter is short*/
bitmap_p += font_p->width_byte - ((w >> 3) + 1);
/*Go to the next row*/
bitmap_p ++;
}
}
/**
* Draw a color map to the display
* @param cords_p coordinates the color map
* @param mask_p the map will drawn only on this area
* @param map_p pointer to a color_t array
* @param opa opacity of the map (ignored, only for compatibility with lv_vmap)
* @param transp true: enable transparency of LV_IMG_COLOR_TRANSP color pixels
*/
void lv_rmap(const area_t * cords_p, const area_t * mask_p,
const color_t * map_p, opa_t opa, bool transp)
{
area_t masked_a;
bool union_ok;
union_ok = area_union(&masked_a, cords_p, mask_p);
/*If there are common part of the mask and map then draw the map*/
if(union_ok == false) return;
/*Go to the first pixel*/
cord_t map_width = area_get_width(cords_p);
map_p+= (masked_a.y1 - cords_p->y1) * map_width;
map_p += masked_a.x1 - cords_p->x1;
if(transp == false) {
cord_t row;
for(row = 0; row < area_get_height(&masked_a); row++) {
cord_t col;
for(col = 0; col < area_get_width(&masked_a); col ++) {
lv_rpx(masked_a.x1 + col, masked_a.y1 + row, mask_p, map_p[col]);
}
map_p += map_width;
}
}else {
color_t transp_color = LV_IMG_COLOR_TRANSP;
cord_t row;
for(row = 0; row < area_get_height(&masked_a); row++) {
cord_t col;
for(col = 0; col < area_get_width(&masked_a); col ++) {
if(map_p[col].full != transp_color.full) {
lv_rpx(masked_a.x1 + col, masked_a.y1 + row, mask_p, map_p[col]);
}
}
map_p += map_width;
}
}
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Put a pixel to the display
* @param x x coordinate of the pixel
* @param y y coordinate of the pixel
* @param mask_p the pixel will be drawn on this area
* @param color color of the pixel
*/
static void lv_rpx(cord_t x, cord_t y, const area_t * mask_p, color_t color)
{
area_t area;
area.x1 = x;
area.y1 = y;
area.x2 = x;
area.y2 = y;
lv_rfill(&area, mask_p, color, OPA_COVER);
}
/**
* @file lv_draw_rbasic..h
*
*/
#ifndef LV_DRAW_RBASIC_H
#define LV_DRAW_RBASIC_H
/*********************
* INCLUDES
*********************/
#include "misc/others/color.h"
#include "../lv_misc/2d.h"
#include "../lv_misc/font.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_rfill(const area_t * area_p, const area_t * mask_p,
color_t color, opa_t opa);
void lv_rletter(const point_t * pos_p, const area_t * mask_p,
const font_t * font_p, uint8_t letter,
color_t color, opa_t opa);
void lv_rmap(const area_t * cords_p, const area_t * mask_p,
const color_t * map_p, opa_t opa, bool transp);
/**********************
* MACROS
**********************/
#endif
/**
* @file lv_vdraw.c
*
*/
#include "../../lv_conf.h"
#if LV_VDB_SIZE != 0
#include <stddef.h>
#include "lvgl/lv_obj/lv_vdb.h"
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_put_vpx(point_t * point_p, const area_t * mask_p,
color_t color, opa_t opa);
static bool lv_vletter_get_px(const font_t * font_p, uint8_t letter, cord_t x, cord_t y);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Fill an area in the Virtual Display Buffer
* @param cords_p coordinates of the area to fill
* @param mask_p fill only o this mask
* @param color fill color
* @param opa opacity of the area (0..255)
*/
void lv_vfill(const area_t * cords_p, const area_t * mask_p,
color_t color, opa_t opa)
{
area_t res_a;
bool union_ok;
lv_vdb_t * vdb_p = lv_vdb_get();
/*Get the union of cord and mask*/
/* The mask is already truncated to the vdb size
* in 'lv_refr_area_with_vdb' function */
union_ok = area_union(&res_a, cords_p, mask_p);
/*If there are common part of the three area then draw to the vdb*/
if(union_ok == true) {
area_t vdb_rel_a; /*Stores relative coordinates on vdb*/
vdb_rel_a.x1 = res_a.x1 - vdb_p->vdb_area.x1;
vdb_rel_a.y1 = res_a.y1 - vdb_p->vdb_area.y1;
vdb_rel_a.x2 = res_a.x2 - vdb_p->vdb_area.x1;
vdb_rel_a.y2 = res_a.y2 - vdb_p->vdb_area.y1;
color_t * vdb_buf_tmp = vdb_p->buf;
uint32_t vdb_width = area_get_width(&vdb_p->vdb_area);
/*Move the vdb_tmp to the first row*/
vdb_buf_tmp += vdb_width * vdb_rel_a.y1;
/*Set all row in vdb to the given color*/
cord_t row;
uint32_t col;
/*Run simpler function without opacity*/
if(opa == OPA_COVER) {
for(row = vdb_rel_a.y1; row <= vdb_rel_a.y2; row++) {
for(col = vdb_rel_a.x1; col <= vdb_rel_a.x2; col++) {
vdb_buf_tmp[col] = color;
}
vdb_buf_tmp += vdb_width;
}
}
/*Calculate the alpha too*/
else {
for(row = vdb_rel_a.y1; row <= vdb_rel_a.y2; row++) {
for(col = vdb_rel_a.x1; col <= vdb_rel_a.x2; col++) {
color_t c = color_mix(color, vdb_buf_tmp[col], opa);
vdb_buf_tmp[col] = c;
}
vdb_buf_tmp += vdb_width;
}
}
}
}
/**
* Draw a letter in the Virtual Display Buffer
* @param pos_p left-top coordinate of the latter
* @param mask_p the letter will be drawn only on this area
* @param font_p pointer to font
* @param letter a letter to draw
* @param color color of letter
* @param opa opacity of letter (0..255)
*/
void lv_vletter(const point_t * pos_p, const area_t * mask_p,
const font_t * font_p, uint8_t letter,
color_t color, opa_t opa)
{
if(font_p == NULL) return;
uint8_t w = font_get_width(font_p, letter);
uint8_t h = font_get_height(font_p);
/*If the letter is completely out of mask don't draw it */
if(pos_p->x + w < mask_p->x1 || pos_p->x > mask_p->x2 ||
pos_p->y + h < mask_p->y1 || pos_p->y > mask_p->y2) return;
cord_t col, row;
point_t act_point;
for(row = 0; row < h; row ++) {
for(col = 0; col < w; col ++) {
act_point.x = pos_p->x + col;
act_point.y = pos_p->y + row;
if(lv_vletter_get_px(font_p, letter, col, row)) {
lv_put_vpx(&act_point, mask_p, color, opa);
}
}
}
}
/**
* Draw a color map to the display
* @param cords_p coordinates the color map
* @param mask_p the map will drawn only on this area
* @param map_p pointer to a color_t array
* @param opa opacity of the map (ignored, only for compatibility with lv_vmap)
* @param transp true: enable transparency of LV_IMG_COLOR_TRANSP color pixels
*/
void lv_vmap(const area_t * cords_p, const area_t * mask_p,
const color_t * map_p, opa_t opa, bool transp)
{
area_t masked_a;
bool union_ok;
lv_vdb_t * vdb_p = lv_vdb_get();
/*Get the union of map size and mask*/
/* The mask is already truncated to the vdb size
* in 'lv_refr_area_with_vdb' function */
union_ok = area_union(&masked_a, cords_p, mask_p);
/*If there are common part of the three area then draw to the vdb*/
if(union_ok == false) return;
uint8_t ds_shift = 0;
#if LV_DOWNSCALE <= 1 || LV_UPSCALE_MAP == 0
ds_shift = 0;
#elif LV_DOWNSCALE == 2
ds_shift = 1;
#elif LV_DOWNSCALE == 4
ds_shift = 2;
#else
#error "LV: not supported LV_DOWNSCALE value"
#endif
/*If the map starts OUT of the masked area then calc. the first pixel*/
cord_t map_width = area_get_width(cords_p) >> ds_shift;
if(cords_p->y1 < masked_a.y1) {
map_p += (uint32_t) map_width * ((masked_a.y1 - cords_p->y1) >> ds_shift);
}
if(cords_p->x1 < masked_a.x1) {
map_p += (masked_a.x1 - cords_p->x1) >> ds_shift;
}
/*Stores coordinates relative to the act vdb*/
masked_a.x1 = masked_a.x1 - vdb_p->vdb_area.x1;
masked_a.y1 = masked_a.y1 - vdb_p->vdb_area.y1;
masked_a.x2 = masked_a.x2 - vdb_p->vdb_area.x1;
masked_a.y2 = masked_a.y2 - vdb_p->vdb_area.y1;
cord_t vdb_width = area_get_width(&vdb_p->vdb_area);
color_t * vdb_buf_tmp = vdb_p->buf;
vdb_buf_tmp += (uint32_t) vdb_width * masked_a.y1; /*Move to the first row*/
map_p -= masked_a.x1 >> ds_shift;
#if LV_DOWNSCALE > 1 && LV_UPSCALE_MAP != 0
cord_t row;
cord_t col;
color_t transp_color = LV_IMG_COLOR_TRANSP;
cord_t map_i;
map_p -= map_width; /*Compensate the first row % LV_DOWNSCALE*/
for(row = masked_a.y1; row <= masked_a.y2; row++) {
if(row % LV_DOWNSCALE == 0) map_p += map_width; /*Next row on the map*/
map_i = masked_a.x1 >> ds_shift;
map_i--; /*Compensate the first col % LV_DOWNSCALE*/
for(col = masked_a.x1; col <= masked_a.x2; col++) {
if(col % LV_DOWNSCALE == 0) map_i++;
if(transp == false || map_p[map_i].full != transp_color.full) {
vdb_buf_tmp[col] = color_mix(map_p[map_i], vdb_buf_tmp[col], opa);
}
}
vdb_buf_tmp += vdb_width; /*Next row on the VDB*/
}
#else
if(transp == false) { /*Simply copy the pixels to the VDB*/
cord_t row;
if(opa == OPA_COVER) { /*no opa */
for(row = masked_a.y1; row <= masked_a.y2; row++) {
memcpy(&vdb_buf_tmp[masked_a.x1],
&map_p[masked_a.x1],
area_get_width(&masked_a) * sizeof(color_t));
map_p += map_width; /*Next row on the map*/
vdb_buf_tmp += vdb_width; /*Next row on the VDB*/
}
} else {
cord_t col;
for(row = masked_a.y1; row <= masked_a.y2; row++) {
for(col = masked_a.x1; col <= masked_a.x2; col ++) {
vdb_buf_tmp[col] = color_mix( map_p[col], vdb_buf_tmp[col], opa);
}
map_p += map_width; /*Next row on the map*/
vdb_buf_tmp += vdb_width; /*Next row on the VDB*/
}
}
} else { /*transp == true: Check all pixels */
cord_t row;
cord_t col;
color_t transp_color = LV_IMG_COLOR_TRANSP;
if(opa == OPA_COVER) { /*no opa */
for(row = masked_a.y1; row <= masked_a.y2; row++) {
for(col = masked_a.x1; col <= masked_a.x2; col ++) {
if(map_p[col].full != transp_color.full) {
vdb_buf_tmp[col] = map_p[col];
}
}
map_p += map_width; /*Next row on the map*/
vdb_buf_tmp += vdb_width; /*Next row on the VDB*/
}
} else {
for(row = masked_a.y1; row <= masked_a.y2; row++) {
for(col = masked_a.x1; col <= masked_a.x2; col ++) {
if(map_p[col].full != transp_color.full) {
vdb_buf_tmp[col] = color_mix( map_p[col], vdb_buf_tmp[col], opa);
}
}
map_p += map_width; /*Next row on the map*/
vdb_buf_tmp += vdb_width; /*Next row on the VDB*/
}
}
}
#endif /*No upscale and no downscale*/
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Put a pixel into the Virtual Dispaly Buffer
* @param x x coordinate of the pixel
* @param y y coordinate of the pixel
* @param mask_p the pixel will be drawn on this area
* @param color color of the pixel
* @param opa opacity of the pixel
*/
static void lv_put_vpx(point_t * point_p, const area_t * mask_p,
color_t color, opa_t opa)
{
if(opa == OPA_TRANSP) return;
bool point_ok;
lv_vdb_t * vdb_p = lv_vdb_get();
/*The point is on vdb?*/
point_ok = area_is_point_on(mask_p, point_p);
/*If there are common part of the three area then draw to the vdb*/
if(point_ok == false) return;
point_t vdb_rel_point; /*Stores relative coordinates on vdb*/
vdb_rel_point.x = point_p->x - vdb_p->vdb_area.x1;
vdb_rel_point.y = point_p->y - vdb_p->vdb_area.y1;
color_t * vdb_buf_tmp = vdb_p->buf;
uint32_t vdb_width = vdb_p->vdb_area.x2 - vdb_p->vdb_area.x1 + 1;
/*Move the vdb_tmp to the point*/
vdb_buf_tmp += vdb_width * vdb_rel_point.y + vdb_rel_point.x;
if(opa == OPA_COVER) *vdb_buf_tmp = color;
else *vdb_buf_tmp = color_mix(color, *vdb_buf_tmp, opa);
}
/**
* Get a pixel from a letter
* @param font_p pointer to a font
* @param letter a letter
* @param x x coordinate of the pixel to get
* @param y y coordinate of the pixel to get
* @return true: pixel is set, false: pixel is clear
*/
static bool lv_vletter_get_px(const font_t * font_p, uint8_t letter, cord_t x, cord_t y)
{
uint8_t w = font_get_width(font_p, letter);
uint8_t h = font_get_height(font_p);
const uint8_t * map_p = font_get_bitmap(font_p, letter);
if(map_p == NULL) return NULL;
if(x < 0) x = 0;
if(y < 0) x = 0;
if(x >= w) x = w - 1;
if(y >= h) y = h - 1;
#if LV_UPSCALE_FONT != 0
#if LV_DOWNSCALE == 1
/*Do nothing*/
#elif LV_DOWNSCALE == 2
x = x >> 1;
y = y >> 1;
#elif LV_DOWNSCALE == 4
x = x >> 2;
y = y >> 2;
#else
#error "LV: not supported LV_DOWNSCALE value"
#endif
#endif /*LV_UPSCALE_FONT == 0*/
map_p += (uint32_t)y * font_p->width_byte; /*Go to the corresponding row of the map*/
map_p += (x >> 3); /*Go to he corresponding col of the map*/
/*Get the corresponding col within a byte*/
uint8_t map_byte = *map_p;
uint8_t col_sub = 7 - (x % 8);
if((map_byte & (1 << col_sub)) == 0) return false;
else return true;
}
#endif
/**
* @file lv_draw_vbasic.h
*
*/
#ifndef LV_DRAW_VBASIC_H
#define LV_DRAW_VBASIC_H
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if LV_VDB_SIZE != 0
#include "misc/others/color.h"
#include "../lv_misc/2d.h"
#include "../lv_misc/font.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_vfill(const area_t * cords_p, const area_t * mask_p,
color_t color, opa_t opa);
void lv_vletter(const point_t * pos_p, const area_t * mask_p,
const font_t * font_p, uint8_t letter,
color_t color, opa_t opa);
void lv_vmap(const area_t * cords_p, const area_t * mask_p,
const color_t * map_p, opa_t opa, bool transp);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file 2d.c
*
*/
/*********************
* INCLUDES
*********************/
#include <lvgl/lv_misc/2d.h>
#include "misc/math/math_base.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize an area
* @param area_p pointer to an area
* @param x1 left coordinate of the area
* @param y1 top coordinate of the area
* @param x2 right coordinate of the area
* @param y2 bottom coordinate of the area
*/
void area_set(area_t * area_p, cord_t x1, cord_t y1, cord_t x2, cord_t y2)
{
area_p->x1 = x1;
area_p->y1 = y1;
area_p->x2 = x2;
area_p->y2 = y2;
}
/**
* Return with area of an area (x * y)
* @param area_p pointer to an area
* @return size of area
*/
uint32_t area_get_size(const area_t * area_p)
{
uint32_t size;
size = (uint32_t)(area_p->x2 - area_p->x1 + 1) *
(area_p->y2 - area_p->y1 + 1);
return size;
}
/**
* Get the common parts of two areas
* @param res_p pointer to an area, the result will be stored her
* @param a1_p pointer to the first area
* @param a2_p pointer to the second area
* @return false: the two area has NO common parts, res_p is invalid
*/
bool area_union(area_t * res_p, const area_t * a1_p, const area_t * a2_p)
{
/* Get the smaller area from 'a1_p' and 'a2_p' */
res_p->x1 = max(a1_p->x1, a2_p->x1);
res_p->y1 = max(a1_p->y1, a2_p->y1);
res_p->x2 = min(a1_p->x2, a2_p->x2);
res_p->y2 = min(a1_p->y2, a2_p->y2);
/*If x1 or y1 greater then x2 or y2 then the areas union is empty*/
bool union_ok = true;
if((res_p->x1 > res_p->x2) ||
(res_p->y1 > res_p->y2))
{
union_ok = false;
}
return union_ok;
}
/**
* Join two areas into a third which involves the other two
* @param res_p pointer to an area, the result will be stored here
* @param a1_p pointer to the first area
* @param a2_p pointer to the second area
*/
void area_join(area_t * a_res_p, const area_t * a1_p, const area_t * a2_p)
{
a_res_p->x1 = min(a1_p->x1, a2_p->x1);
a_res_p->y1 = min(a1_p->y1, a2_p->y1);
a_res_p->x2 = max(a1_p->x2, a2_p->x2);
a_res_p->y2 = max(a1_p->y2, a2_p->y2);
}
/**
* Check if a point is on an area
* @param a_p pointer to an area
* @param p_p pointer to a point
* @return false:the point is out of the area
*/
bool area_is_point_on(const area_t * a_p, const point_t * p_p)
{
bool is_on = false;
if((p_p->x >= a_p->x1 && p_p->x <= a_p->x2) &&
((p_p->y >= a_p->y1 && p_p->y <= a_p->y2)))
{
is_on = true;
}
return is_on;
}
/**
* Check if two area has common parts
* @param a1_p pointer to an area.
* @param a2_p pointer to an other area
* @return false: a1_p and a2_p has no common parts */
bool area_is_on(const area_t * a1_p, const area_t * a2_p)
{
/*Two area are on each other if... */
point_t p;
/*a2 left-top corner is on a1*/
p.x = a2_p->x1;
p.y = a2_p->y1;
if(area_is_point_on(a1_p, &p)) return true;
/*a2 right-top corner is on a1*/
p.x = a2_p->x1;
p.y = a2_p->y1;
if(area_is_point_on(a1_p, &p)) return true;
/*a2 left-bottom corner is on a1*/
p.x = a2_p->x1;
p.y = a2_p->y2;
if(area_is_point_on(a1_p, &p)) return true;
/*a2 right-bottom corner is on a1*/
p.x = a2_p->x2;
p.y = a2_p->y2;
if(area_is_point_on(a1_p, &p)) return true;
/*a2 is horizontally bigger then a1 and covers it*/
if((a2_p->x1 <= a1_p->x1 && a2_p->x2 >= a1_p->x2) && /*a2 hor. cover a1?*/
((a2_p->y1 <= a1_p->y1 && a2_p->y1 >= a1_p->y2) || /*upper edge is on a1?*/
(a2_p->y2 <= a1_p->y1 && a2_p->y2 >= a1_p->y2) ||/* or lower edge is on a1?*/
(a2_p->y1 <= a1_p->y1 && a2_p->y2 >= a1_p->y2))) /*or a2 vert bigger then a1*/
return true;
/*a2 is vertically bigger then a1 and covers it*/
if((a2_p->y1 <= a1_p->y1 && a2_p->y2 >= a1_p->y2) && /*a2 vert. cover a1?*/
((a2_p->x1 <= a1_p->x1 && a2_p->x1 >= a1_p->x2) || /*left edge is on a1?*/
(a2_p->x2 <= a1_p->x1 && a2_p->x2 >= a1_p->x2) ||/* or right edge is on a1?*/
(a2_p->x1 <= a1_p->x1 && a2_p->x2 >= a1_p->x2))) /*or a2 hor. bigger then a1*/
return true;
/*Else no cover*/
return false;
}
/**
* Check if an area is fully on an other
* @param ain_p pointer to an area which could be on aholder_p
* @param aholder pointer to an area which could involve ain_p
* @return
*/
bool area_is_in(const area_t * ain_p, const area_t * aholder_p)
{
bool is_in = false;
if(ain_p->x1 >= aholder_p->x1 &&
ain_p->y1 >= aholder_p->y1 &&
ain_p->x2 <= aholder_p->x2 &&
ain_p->y2 <= aholder_p->y2)
{
is_in = true;
}
return is_in;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* @file 2d.h
*
*/
#ifndef _2D_H
#define _2D_H
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef LV_CORD_TYPE cord_t;
typedef struct
{
cord_t x;
cord_t y;
}point_t;
typedef struct
{
cord_t x1;
cord_t y1;
cord_t x2;
cord_t y2;
}area_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
static void inline area_cpy(area_t * dest, const area_t * src)
{
memcpy(dest, src, sizeof(area_t));
}
static inline cord_t area_get_width(const area_t * area_p)
{
return area_p->x2 - area_p->x1 + 1;
}
static inline cord_t area_get_height(const area_t * area_p)
{
return area_p->y2 - area_p->y1 + 1;
}
void area_set(area_t * area_p, cord_t x1, cord_t y1, cord_t x2, cord_t y2);
uint32_t area_get_size(const area_t * area_p);
bool area_union(area_t * res_p, const area_t * a1_p, const area_t * a2_p);
void area_join(area_t * a_res_p, const area_t * a1_p, const area_t * a2_p);
bool area_is_point_on(const area_t * a_p, const point_t * p_p);
bool area_is_on(const area_t * a1_p, const area_t * a2_p);
bool area_is_in(const area_t * a_in, const area_t * a_holder);
/**********************
* MACROS
**********************/
#endif
/**
* @file circ.c
* Circle drawing algorithm (with Bresenham)
* Only a 1/8 circle is calculated. Use CIRC_OCT1_X, CIRC_OCT1_Y macros to get
* the other octets.
*/
/*********************
* INCLUDES
*********************/
#include <lvgl/lv_misc/2d.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize the circle drawing
* @param c pointer to a point. The coordinates will be calculated here
* @param tmp point to a variable. It will store temporary data
* @param radius radius of the circle
*/
void circ_init(point_t * c, cord_t * tmp, cord_t radius)
{
c->x = radius;
c->y = 0;
*tmp = 1 - radius;
}
/**
* Test the circle drawing is ready or not
* @param c same as in circ_init
* @return true if the circle is not ready yet
*/
bool circ_cont(point_t * c)
{
return c->y <= c->x ? true : false;
}
/**
* Get the next point from the circle
* @param c same as in circ_init. The next point stored here.
* @param tmp same as in circ_init.
*/
void circ_next(point_t * c, cord_t * tmp)
{
c->y++;
if (*tmp <= 0) {
(*tmp) += 2 * c->y + 1; // Change in decision criterion for y -> y+1
} else {
c->x--;
(*tmp) += 2 * (c->y - c->x) + 1; // Change for y -> y+1, x -> x-1
}
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* @file circ.h
*
*/
#ifndef CIRC_H
#define CIRC_H
/*********************
* INCLUDES
*********************/
#include <lvgl/lv_misc/2d.h>
#include <stddef.h>
/*********************
* DEFINES
*********************/
#define CIRC_OCT1_X(p) (p.x)
#define CIRC_OCT1_Y(p) (p.y)
#define CIRC_OCT2_X(p) (p.y)
#define CIRC_OCT2_Y(p) (p.x)
#define CIRC_OCT3_X(p) (-p.y)
#define CIRC_OCT3_Y(p) (p.x)
#define CIRC_OCT4_X(p) (-p.x)
#define CIRC_OCT4_Y(p) (p.y)
#define CIRC_OCT5_X(p) (-p.x)
#define CIRC_OCT5_Y(p) (-p.y)
#define CIRC_OCT6_X(p) (-p.y)
#define CIRC_OCT6_Y(p) (-p.x)
#define CIRC_OCT7_X(p) (p.y)
#define CIRC_OCT7_Y(p) (-p.x)
#define CIRC_OCT8_X(p) (p.x)
#define CIRC_OCT8_Y(p) (-p.y)
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void circ_init(point_t * c, cord_t * tmp, cord_t radius);
bool circ_cont(point_t * c);
void circ_next(point_t * c, cord_t * tmp);
/**********************
* MACROS
**********************/
#endif
/**
* @file font.c
*
*/
/*********************
* INCLUDES
*********************/
#include <stddef.h>
#include "font.h"
#include "fonts/dejavu_14.h"
#include "fonts/dejavu_20.h"
#include "fonts/dejavu_30.h"
#include "fonts/dejavu_40.h"
#include "fonts/dejavu_60.h"
#include "fonts/dejavu_80.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Get the font from its id
* @param font_id: the id of a font (an element of font_types_t enum)
* @return pointer to a font descriptor
*/
const font_t * font_get(font_types_t font_id)
{
const font_t * font_p = NULL;
switch(font_id)
{
#if USE_FONT_DEJAVU_14 != 0
case FONT_DEJAVU_14:
font_p = dejavu_14_get_dsc();
break;
#endif
#if USE_FONT_DEJAVU_20 != 0
case FONT_DEJAVU_20:
font_p = dejavu_20_get_dsc();
break;
#endif
#if USE_FONT_DEJAVU_30 != 0
case FONT_DEJAVU_30:
font_p = dejavu_30_get_dsc();
break;
#endif
#if USE_FONT_DEJAVU_40 != 0
case FONT_DEJAVU_40:
font_p = dejavu_40_get_dsc();
break;
#endif
#if USE_FONT_DEJAVU_60 != 0
case FONT_DEJAVU_60:
font_p = dejavu_60_get_dsc();
break;
#endif
#if USE_FONT_DEJAVU_80 != 0
case FONT_DEJAVU_80:
font_p = dejavu_80_get_dsc();
break;
#endif
default:
font_p = NULL;
}
return font_p;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* @file font.h
*
*/
#ifndef FONT_H
#define FONT_H
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#include <stdint.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum
{
#if USE_FONT_DEJAVU_14
FONT_DEJAVU_14,
#endif
#if USE_FONT_DEJAVU_20
FONT_DEJAVU_20,
#endif
#if USE_FONT_DEJAVU_30
FONT_DEJAVU_30,
#endif
#if USE_FONT_DEJAVU_40
FONT_DEJAVU_40,
#endif
#if USE_FONT_DEJAVU_60
FONT_DEJAVU_60,
#endif
#if USE_FONT_DEJAVU_80
FONT_DEJAVU_80,
#endif
FONT_TYPE_NUM,
}font_types_t;
typedef struct
{
uint8_t letter_cnt;
uint8_t start_ascii;
uint8_t width_byte;
uint8_t height_row;
uint8_t fixed_width;
const uint8_t * width_bit_a;
const uint8_t * bitmaps_a;
}font_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
const font_t * font_get(font_types_t letter);
/**********************
* MACROS
**********************/
/**
* Return with the bitmap of a font.
* @param font_p pointer to a font
* @param letter a letter
* @return pointer to the bitmap of the letter
*/
static inline const uint8_t * font_get_bitmap(const font_t * font_p, uint8_t letter)
{
uint32_t index = (letter - font_p->start_ascii) * font_p->height_row * font_p->width_byte;
return &font_p->bitmaps_a[index];
}
/**
* Get the height of a font
* @param font_p pointer to a font
* @return the height of a font
*/
static inline uint8_t font_get_height(const font_t * font_p)
{
#if LV_DOWNSCALE > 1 && LV_UPSCALE_FONT != 0
return font_p->height_row * LV_DOWNSCALE;
#else
return font_p->height_row;
#endif
}
/**
* Get the width of a letter in a font
* @param font_p pointer to a font
* @param letter a letter
* @return the width of a letter
*/
static inline uint8_t font_get_width(const font_t * font_p, uint8_t letter)
{
if(letter < font_p->start_ascii) return 0;
letter -= font_p->start_ascii;
uint8_t w = 0;
if(letter < font_p->letter_cnt) {
w = font_p->fixed_width != 0 ? font_p->fixed_width :
font_p->width_bit_a[letter];
}
#if LV_DOWNSCALE > 1 && LV_UPSCALE_FONT != 0
return w * LV_DOWNSCALE;
#else
return w;
#endif
}
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef DEJAVU_14_H
#define DEJAVU_14_H
/*Use ISO8859-1 encoding in the IDE*/
#include "lv_conf.h"
#if USE_FONT_DEJAVU_14 != 0
#include <stdint.h>
#include "../font.h"
const font_t * dejavu_14_get_dsc(void);
#endif
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef DEJAVU_20_H
#define DEJAVU_20_H
/*Use ISO8859-1 encoding in the IDE*/
#include "misc_conf.h"
#if USE_FONT_DEJAVU_20 != 0
#include <stdint.h>
#include "../font.h"
const font_t * dejavu_20_get_dsc(void);
#endif
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef DEJAVU_30_H
#define DEJAVU_30_H
/*Use ISO8859-1 encoding in the IDE*/
#include "lv_conf.h"
#if USE_FONT_DEJAVU_30 != 0
#include <stdint.h>
#include "../font.h"
const font_t * dejavu_30_get_dsc(void);
#endif
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef DEJAVU_40_H
#define DEJAVU_40_H
/*Use ISO8859-1 encoding in the IDE*/
#include "lv_conf.h"
#if USE_FONT_DEJAVU_40 != 0
#include <stdint.h>
#include "../font.h"
const font_t * dejavu_40_get_dsc(void);
#endif
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef DEJAVU_60_H
#define DEJAVU_60_H
/*Use ISO8859-1 encoding in the IDE*/
#include "lv_conf.h"
#if USE_FONT_DEJAVU_60 != 0
#include <stdint.h>
#include "../font.h"
const font_t * dejavu_60_get_dsc(void);
#endif
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef DEJAVU_80_H
#define DEJAVU_80_H
/*Use ISO8859-1 encoding in the IDE*/
#include "lv_conf.h"
#if USE_FONT_DEJAVU_80 != 0
#include <stdint.h>
#include "../font.h"
const font_t * dejavu_80_get_dsc(void);
#endif
#endif
/**
* @file font.c
*
*/
/*********************
* INCLUDES
*********************/
#include "text.h"
/*********************
* DEFINES
*********************/
#define TXT_NO_BREAK_FOUND UINT16_MAX
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool txt_is_break_char(char letter);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Get the next line of text. Check line length and break chars too.
* @param txt a '\0' terminated string
* @param font_p pointer to a font
* @param letter_space letter space
* @param max_l max line length
* @return the index of the first char of the new line
*/
uint16_t txt_get_next_line(const char * txt, const font_t * font_p,
uint16_t letter_space, cord_t max_l)
{
uint32_t i = 0;
cord_t act_l = 0;
uint16_t last_break = TXT_NO_BREAK_FOUND;
while(txt[i] != '\0') {
/*Check for new line chars*/
if(txt[i] == '\n' || txt[i] == '\r') {
/*Handle \n\r and \r\n as well*/
if(txt[i + 1] == '\n' || txt[i + 1] == '\r') {
i++;
}
return i+1; /*Return with the first letter of the next line*/
} else { /*Check the actual length*/
act_l += font_get_width(font_p, txt[i]);
/*If the txt is too long then finish, this is the line end*/
if(act_l >= max_l) {
/*If already a break character is found, then break there*/
if(last_break != TXT_NO_BREAK_FOUND) {
i = last_break;
}
while(txt[i] == ' ') i++;
return i;
}
/*If this char still can fit to this line then check if
* txt can be broken here later */
else if(txt_is_break_char(txt[i])) {
last_break = i;
last_break++;/*Go to the next char, the break char stays in this line*/
}
}
act_l += letter_space;
i++;
}
return i;
}
/**
* Give the length of a text with a given font
* @param txt a '\0' terminate string
* @param char_num number of characters in 'txt'
* @param font_p pointer to a font
* @param letter_space letter sapce
* @return length of a char_num long text
*/
cord_t txt_get_length(const char * txt, uint16_t char_num,
const font_t * font_p, uint16_t letter_space)
{
uint16_t i;
cord_t len = 0;
if(char_num != 0) {
for(i = 0; i < char_num; i++) {
len += font_get_width(font_p, txt[i]);
len += letter_space;
}
/*Trim closing spaces */
for(i = char_num - 1; i > 0; i--) {
if(txt[i] == ' ') {
len -= font_get_width(font_p, txt[i]);
len -= letter_space;
} else {
break;
}
}
/*Correct the last letter space,
* because thee is no letter space after the last char*/
len -= letter_space;
}
return len;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Test if char is break char or not (a text can broken here or not)
* @param letter a letter
* @return false: 'letter' is not break char
*/
static bool txt_is_break_char(char letter)
{
uint8_t i;
bool ret = false;
/*Compare the letter to TXT_BREAK_CHARS*/
for(i = 0; LV_TXT_BREAK_CHARS[i] != '\0'; i++) {
if(letter == LV_TXT_BREAK_CHARS[i]) {
ret = true; /*If match then it is break char*/
break;
}
}
return ret;
}
/**
* @file text.h
*
*/
#ifndef TEXT_H
#define TEXT_H
/*********************
* INCLUDES
*********************/
#include <lvgl/lv_misc/2d.h>
#include <stdbool.h>
#include "font.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
uint16_t txt_get_next_line(const char * txt, const font_t * font_p, uint16_t letter_space, cord_t max_l);
cord_t txt_get_length(const char * txt, uint16_t char_num, const font_t * font_p, uint16_t letter_space);
/**********************
* MACROS
**********************/
#endif
/**
* @file lv_dispi.c
*
*/
/*********************
* INCLUDES
********************/
#include "../../lv_conf.h"
#include "misc/os/ptask.h"
#include "misc/math/math_base.h"
#include "lv_dispi.h"
#include "../lv_draw/lv_draw_rbasic.h"
#include "hal/indev/indev.h"
#include "hal/systick/systick.h"
#include "lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void dispi_task(void);
static void dispi_proc_point(lv_dispi_t * dispi_p, cord_t x, cord_t y);
static void dispi_proc_press(lv_dispi_t * dispi_p);
static void disi_proc_release(lv_dispi_t * dispi_p);
static lv_obj_t* dispi_search_obj(const lv_dispi_t * dispi_p, lv_obj_t* obj_dp);
static void dispi_drag(lv_dispi_t * dispi_p);
static void dispi_drag_throw(lv_dispi_t * dispi_p);
/**********************
* STATIC VARIABLES
**********************/
static ptask_t* dispi_task_p;
static bool lv_dispi_reset_qry;
static bool lv_dispi_reset_now;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize the display input subsystem
*/
void lv_dispi_init(void)
{
lv_dispi_reset_qry = false;
lv_dispi_reset_now = false;
#if LV_DISPI_READ_PERIOD != 0
dispi_task_p = ptask_create(dispi_task, LV_DISPI_READ_PERIOD, PTASK_PRIO_MID);
#else
dispi_task_p = ptask_create(dispi_task, 1, PTASK_PRIO_OFF); /*Not use lv_dispi*/
#endif
}
/**
* Reset all display inputs
*/
void lv_dispi_reset(void)
{
lv_dispi_reset_qry = true;
}
/**
* Get the last point on display input
* @param dispi_p pointer to a display input
* @param point_p pointer to a point to store the result
*/
void lv_dispi_get_point(lv_dispi_t * dispi_p, point_t * point_p)
{
point_p->x = dispi_p->act_point.x;
point_p->y = dispi_p->act_point.y;
}
/**
* Check if there is dragging on display input or not
* @param dispi_p pointer to a display input
* @return true: drag is in progress
*/
bool lv_dispi_is_dragging(lv_dispi_t * dispi_p)
{
return dispi_p->drag_in_prog == 0 ? false : true;
}
/**
* Get the vector of dragging on a display input
* @param dispi_p pointer to a display input
* @param point_p pointer to a point to store the vector
*/
void lv_dispi_get_vect(lv_dispi_t * dispi_p, point_t * point_p)
{
point_p->x = dispi_p->vect.x;
point_p->y = dispi_p->vect.y;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Called periodically to handle the display inputs
*/
static void dispi_task(void)
{
static lv_dispi_t dispi[INDEV_NUM];
cord_t x;
cord_t y;
uint8_t i;
for (i = 0; i < INDEV_NUM; i++) {
dispi[i].pressed = indev_get(i, &x, &y);
dispi_proc_point(&dispi[i], x, y);
}
/*If reset query occurred in this round then set a flag to
* ask the dispis to reset themself in the next round */
if(lv_dispi_reset_qry != false) {
lv_dispi_reset_qry = false;
lv_dispi_reset_now = true;
}
/*If now a reset occurred then clear the flag*/
else if (lv_dispi_reset_now != false){
lv_dispi_reset_now = false;
}
}
/**
* Process new points by a display input. dispi_p->pressed has to be set
* @param dispi_p pointer to a display input
* @param x x coordinate of the next point
* @param y y coordinate of the next point
*/
static void dispi_proc_point(lv_dispi_t * dispi_p, cord_t x, cord_t y)
{
#if LV_DOWNSCALE > 1 && LV_VDB_SIZE != 0
dispi_p->act_point.x = x * LV_DOWNSCALE;
dispi_p->act_point.y = y * LV_DOWNSCALE;
#else
dispi_p->act_point.x = x;
dispi_p->act_point.y = y;
#endif
/*Handle the reset query*/
if(lv_dispi_reset_now != false) {
dispi_p->act_obj_dp = NULL;
dispi_p->last_obj_dp = NULL;
dispi_p->drag_in_prog = 0;
dispi_p->long_press_sent = 0;
dispi_p->press_time_stamp = 0;
dispi_p->vect_sum.x = 0;
dispi_p->vect_sum.y = 0;
}
if(dispi_p->pressed != false){
#if LV_DISPI_TP_MARKER != 0
area_t area;
area.x1 = x;
area.y1 = y;
area.x2 = x + 1;
area.y2 = y + 1;
lv_rfill(&area, NULL, COLOR_MAKE(0xFF, 0, 0), OPA_COVER);
#endif
dispi_proc_press(dispi_p);
} else {
disi_proc_release(dispi_p);
}
dispi_p->last_point.x = dispi_p->act_point.x;
dispi_p->last_point.y = dispi_p->act_point.y;
}
/**
* Process the pressed state
* @param dispi_p pointer to a display input
*/
static void dispi_proc_press(lv_dispi_t * dispi_p)
{
lv_obj_t* pr_obj_dp = dispi_p->act_obj_dp;
/*If there is no last object then search*/
if(dispi_p->act_obj_dp == NULL) {
pr_obj_dp = dispi_search_obj(dispi_p, lv_scr_act());
}
/*If there is last object but it can not be dragged also search*/
else if(lv_obj_get_drag(dispi_p->act_obj_dp) == false) {/*Now act_obj_dp != NULL*/
pr_obj_dp = dispi_search_obj(dispi_p, lv_scr_act());
}
/*If a dragable object was the last then keep it*/
else {
}
/*If a new object was found reset some variables and send a pressed signal*/
if(pr_obj_dp != dispi_p->act_obj_dp) {
dispi_p->last_point.x = dispi_p->act_point.x;
dispi_p->last_point.y = dispi_p->act_point.y;
/*If a new object found the previous was lost, so send a signal*/
if(dispi_p->act_obj_dp != NULL) {
dispi_p->act_obj_dp->signal_f(dispi_p->act_obj_dp,
LV_SIGNAL_PRESS_LOST, dispi_p);
}
if(pr_obj_dp != NULL) {
/* Save the time when the obj pressed.
* It is necessary to count the long press time.*/
dispi_p->press_time_stamp = systick_get();
dispi_p->long_press_sent = 0;
dispi_p->drag_in_prog = 0;
dispi_p->vect_sum.x = 0;
dispi_p->vect_sum.y = 0;
/*Search for 'top' attribute*/
lv_obj_t * i = pr_obj_dp;
lv_obj_t * last_top = NULL;
while(i != NULL){
if(i->top_en != 0) last_top = i;
i = lv_obj_get_parent(i);
}
if(last_top != NULL) {
/*Move the last_top object to the foreground*/
lv_obj_t * par_dp =lv_obj_get_parent(last_top);
/*After list change it will be the new head*/
ll_chg_list(&par_dp->child_ll, &par_dp->child_ll, last_top);
lv_obj_inv(last_top);
}
/*Send a signal about the press*/
pr_obj_dp->signal_f(pr_obj_dp, LV_SIGNAL_PRESSED, dispi_p);
}
}
/*The reset can be set in the signal function.
* In case of reset query ignore the remaining parts.*/
if(lv_dispi_reset_qry == false) {
dispi_p->act_obj_dp = pr_obj_dp; /*Save the pressed object*/
dispi_p->last_obj_dp = dispi_p->act_obj_dp; /*Refresh the last_obj*/
/*Calculate the vector*/
dispi_p->vect.x = dispi_p->act_point.x - dispi_p->last_point.x;
dispi_p->vect.y = dispi_p->act_point.y - dispi_p->last_point.y;
/*If there is active object and it can be dragged run the drag*/
if(dispi_p->act_obj_dp != NULL) {
dispi_drag(dispi_p);
/*If there is no drag then check for long press time*/
if(dispi_p->drag_in_prog == 0 && dispi_p->long_press_sent == 0) {
/*Send a signal about the long press if enough time elapsed*/
if(systick_elaps(dispi_p->press_time_stamp) > LV_DISPI_LONG_PRESS_TIME) {
pr_obj_dp->signal_f(pr_obj_dp, LV_SIGNAL_LONG_PRESS, dispi_p);
/*Mark the signal sending to do not send it again*/
dispi_p->long_press_sent = 1;
}
}
}
}
}
/**
* Process the released state
* @param dispi_p pointer to a display input
*/
static void disi_proc_release(lv_dispi_t * dispi_p)
{
/*Forgot the act obj and send a released signal */
if(dispi_p->act_obj_dp != NULL) {
dispi_p->act_obj_dp->signal_f(dispi_p->act_obj_dp,
LV_SIGNAL_RELEASED, dispi_p);
dispi_p->act_obj_dp = NULL;
dispi_p->press_time_stamp = 0;
}
/*The reset can be set in the signal function.
* In case of reset query ignore the remaining parts.*/
if(dispi_p->last_obj_dp != NULL && lv_dispi_reset_qry == false) {
dispi_drag_throw(dispi_p);
}
}
/**
* Search the most top, clickable object on the last point of a display input
* @param dispi_p pointer to a display input
* @param obj_dp pointer to a start object, typically the screen
* @return pointer to the found object or NULL if there was no suitable object
*/
static lv_obj_t* dispi_search_obj(const lv_dispi_t * dispi_p, lv_obj_t* obj_dp)
{
lv_obj_t* found_p = NULL;
/*If the point is on this object*/
/*Check its children too*/
if(area_is_point_on(&obj_dp->cords, &dispi_p->act_point)) {
lv_obj_t* i;
LL_READ(obj_dp->child_ll, i) {
found_p = dispi_search_obj(dispi_p, i);
/*If a child was found then break*/
if(found_p != NULL) {
break;
}
}
/*If then the children was not ok, but this obj is clickable
* and it or its parent is not hidden then save this object*/
if(found_p == NULL && lv_obj_get_click(obj_dp) != false) {
lv_obj_t * i = obj_dp;
while(i != NULL) {
if(lv_obj_get_hidden(i) == true) break;
i = lv_obj_get_parent(i);
}
/*No parent found with hidden == true*/
if(i == NULL) found_p = obj_dp;
}
}
return found_p;
}
/**
* Handle the dragging of dispi_p->act_obj_dp
* @param dispi_p pointer to a display input
*/
static void dispi_drag(lv_dispi_t * dispi_p)
{
lv_obj_t* par_dp = lv_obj_get_parent(dispi_p->act_obj_dp);
lv_obj_t* drag_obj_dp = dispi_p->act_obj_dp;
if(lv_obj_get_drag_parent(dispi_p->act_obj_dp) != false) {
drag_obj_dp = par_dp;
}
if(lv_obj_get_drag(drag_obj_dp) == false) return;
/*If still there is no drag then count the movement*/
if(dispi_p->drag_in_prog == 0) {
dispi_p->vect_sum.x += dispi_p->vect.x;
dispi_p->vect_sum.y += dispi_p->vect.y;
/*If a move is greater then LV_DRAG_LIMIT then begin the drag*/
if(abs(dispi_p->vect_sum.x) >= LV_DISPI_DRAG_LIMIT ||
abs(dispi_p->vect_sum.y) >= LV_DISPI_DRAG_LIMIT)
{
dispi_p->drag_in_prog = 1;
drag_obj_dp->signal_f(drag_obj_dp,
LV_SIGNAL_DRAG_BEGIN, dispi_p);
}
}
/*If the drag limit is stepped over then handle the dragging*/
if(dispi_p->drag_in_prog != 0) {
/*Set new position if the vector is not zero*/
if(dispi_p->vect.x != 0 ||
dispi_p->vect.y != 0) {
/*Get the coordinates of the object end modify them*/
cord_t act_x = lv_obj_get_x(drag_obj_dp) + dispi_p->vect.x;
cord_t act_y = lv_obj_get_y(drag_obj_dp) + dispi_p->vect.y;
lv_obj_set_pos(drag_obj_dp, act_x, act_y);
}
}
}
/**
* Handle throwing by drag if the drag is ended
* @param dispi_p pointer to a display input
*/
static void dispi_drag_throw(lv_dispi_t * dispi_p)
{
/*Set new position if the vector is not zero*/
lv_obj_t* par_dp = lv_obj_get_parent(dispi_p->last_obj_dp);
lv_obj_t* drag_obj_dp = dispi_p->last_obj_dp;
if(lv_obj_get_drag_parent(dispi_p->last_obj_dp) != false) {
drag_obj_dp = par_dp;
}
/*Return if the drag throw is not enabled*/
if(lv_obj_get_drag_throw(drag_obj_dp) == false ){
dispi_p->drag_in_prog = 0;
drag_obj_dp->signal_f(drag_obj_dp, LV_SIGNAL_DRAG_END, dispi_p);
return;
}
/*Reduce the vectors*/
dispi_p->vect.x = dispi_p->vect.x * (100 -LV_DISPI_DRAG_THROW) / 100;
dispi_p->vect.y = dispi_p->vect.y * (100 -LV_DISPI_DRAG_THROW) / 100;
if(dispi_p->vect.x != 0 ||
dispi_p->vect.y != 0)
{
/*Get the coordinates and modify them*/
cord_t act_x = lv_obj_get_x(drag_obj_dp) + dispi_p->vect.x;
cord_t act_y = lv_obj_get_y(drag_obj_dp) + dispi_p->vect.y;
lv_obj_set_pos(drag_obj_dp, act_x, act_y);
}
/*If the vectors become 0 -> drag_in_prog = 0 and send a drag end signal*/
else {
dispi_p->drag_in_prog = 0;
drag_obj_dp->signal_f(drag_obj_dp, LV_SIGNAL_DRAG_END, dispi_p);
}
}
/**
* @file lv_dispi.h
*
*/
#ifndef LV_DISPI_H
#define LV_DISPI_H
/*********************
* INCLUDES
*********************/
#include "lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct
{
bool pressed;
point_t act_point;
point_t last_point;
point_t vect;
point_t vect_sum;
lv_obj_t* act_obj_dp;
lv_obj_t* last_obj_dp;
uint32_t press_time_stamp;
/*Flags*/
uint8_t drag_in_prog :1;
uint8_t long_press_sent :1;
}lv_dispi_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_dispi_init(void);
void lv_dispi_reset(void);
bool lv_dispi_is_dragging(lv_dispi_t * dispi_p);
void lv_dispi_get_point(lv_dispi_t * dispi_p, point_t * point_p);
void lv_dispi_get_vect(lv_dispi_t * dispi_p, point_t * point_p);
/**********************
* MACROS
**********************/
#endif
\ No newline at end of file
/**
* @file lv_base_obj.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_obj.h"
#include "../lv_draw/lv_draw_rbasic.h"
#include "../lv_draw/lv_draw_vbasic.h"
#include "lv_dispi.h"
#include "lv_refr.h"
/*********************
* DEFINES
*********************/
#define LV_OBJ_DEF_LENGTH 80
#define LV_OBJ_DEF_HEIGHT 60
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_obj_pos_child_refr(lv_obj_t* obj_dp, cord_t x_diff, cord_t y_diff);
static void lv_style_refr_core(void * style_p, lv_obj_t* obj_dp);
static bool lv_obj_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
/**********************
* STATIC VARIABLES
**********************/
lv_obj_t* def_scr_dp = NULL;
lv_obj_t* act_scr_dp = NULL;
ll_dsc_t scr_ll;
lv_objs_t lv_objs_def = {.color = COLOR_GRAY, .empty = 0, .auto_color = 1};
lv_objs_t lv_objs_color = {.color = COLOR_RED, .empty = 0, .auto_color = 0};
lv_objs_t lv_objs_scr = {.color = LV_OBJ_DEF_SCR_COLOR, .empty = 0, .auto_color = 0};
lv_objs_t lv_objs_empty = {.color = COLOR_GRAY, .empty = 1, .auto_color = 0};
lv_objs_t lv_objs_autocolor = {.color = COLOR_GRAY, .empty = 0, .auto_color = 1};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Init. the 'lv' library.
*/
void lv_init(void)
{
/*Clear the screen*/
area_t scr_area;
area_set(&scr_area, 0, 0, LV_HOR_RES, LV_VER_RES);
lv_rfill(&scr_area, NULL, COLOR_BLACK, OPA_COVER);
/*Init. the screen refresh system*/
lv_refr_init();
/*Create the default screen*/
ll_init(&scr_ll, sizeof(lv_obj_t));
def_scr_dp = lv_obj_create(NULL, NULL);
act_scr_dp = def_scr_dp;
/*Refresh the screen*/
lv_obj_inv(act_scr_dp);
#if LV_DISPI_READ_PERIOD != 0
/*Init the display input handling*/
lv_dispi_init();
#endif
}
/**
* Mark the object as invalid therefor it will be redrawn by 'lv_refr_task'
* @param obj_dp pointer to an object
*/
void lv_obj_inv(lv_obj_t* obj_dp)
{
/*Invalidate the object only if it belongs to the 'act_scr'*/
lv_obj_t* act_scr_p = lv_scr_act();
if(lv_obj_get_scr(obj_dp) == act_scr_p) {
/*Truncate the recursively on the parents*/
area_t area_trunc;
lv_obj_t* par_dp = lv_obj_get_parent(obj_dp);
bool union_ok = true;
/*Start with the original coordinates*/
area_cpy(&area_trunc, &obj_dp->cords);
/*Check through all parents*/
while(par_dp != NULL) {
union_ok = area_union(&area_trunc, &area_trunc, &par_dp->cords);
if(union_ok == false) break; /*If no common parts with parent break;*/
par_dp = lv_obj_get_parent(par_dp);
}
if(union_ok != false) lv_inv_area(&area_trunc);
}
}
/**
* Notify an object if its style is modified
* @param obj_dp pointer to an object
*/
void lv_obj_refr_style(lv_obj_t* obj_dp)
{
obj_dp->signal_f(obj_dp, LV_SIGNAL_STYLE_CHG, NULL);
lv_obj_inv(obj_dp);
}
/**
* Notify all object if a style is modified
* @param style_p pinter to a style. Only objects with this style will be notified
* (NULL to notify all objects)
*/
void lv_style_refr_all(void * style_p)
{
lv_obj_t* i;
LL_READ(scr_ll, i) {
lv_style_refr_core(style_p, i);
}
}
/*--------------------
* Create and delete
*-------------------*/
/**
* Create a basic object
* @param parent_dp pointer to a parent object.
* If NULL then a screen will be created
* @param copy_dp pointer to a base object, if not NULL then the new object will be copied from it
* @return pointer to the new object
*/
lv_obj_t* lv_obj_create(lv_obj_t* parent_dp, lv_obj_t * copy_dp)
{
lv_obj_t* new_obj_dp = NULL;
/*Create a screen if the parent is NULL*/
if(parent_dp == NULL) {
new_obj_dp = ll_ins_head(&scr_ll);
new_obj_dp->par_dp = NULL; /*Screens has no a parent*/
ll_init(&(new_obj_dp->child_ll), sizeof(lv_obj_t));
/*Set coordinates to full screen size*/
new_obj_dp->cords.x1 = 0;
new_obj_dp->cords.y1 = 0;
new_obj_dp->cords.x2 = LV_HOR_RES - 1;
new_obj_dp->cords.y2 = LV_VER_RES - 1;
/*Set appearance*/
new_obj_dp->style_p = lv_objs_get(LV_OBJS_SCR, NULL);
new_obj_dp->opa = OPA_COVER;
/*Set virtual functions*/
lv_obj_set_signal_f(new_obj_dp, lv_obj_signal);
lv_obj_set_design_f(new_obj_dp, lv_obj_design);
/*Set attributes*/
new_obj_dp->click_en = 0;
new_obj_dp->drag_en = 0;
new_obj_dp->drag_throw_en = 0;
new_obj_dp->drag_parent = 0;
new_obj_dp->style_iso = 0;
new_obj_dp->hidden = 0;
new_obj_dp->top_en = 0;
new_obj_dp->ext_dp = NULL;
}
/*parent_dp != NULL create normal obj. on parent*/
else
{
new_obj_dp = ll_ins_head(&(parent_dp)->child_ll);
new_obj_dp->par_dp = parent_dp; /*Set the parent*/
ll_init(&(new_obj_dp->child_ll), sizeof(lv_obj_t));
/*Set coordinates left top corner of parent*/
new_obj_dp->cords.x1 = parent_dp->cords.x1;
new_obj_dp->cords.y1 = parent_dp->cords.y1;
new_obj_dp->cords.x2 = parent_dp->cords.x1 +
LV_OBJ_DEF_LENGTH * LV_DOWNSCALE;
new_obj_dp->cords.y2 = parent_dp->cords.y1 +
LV_OBJ_DEF_HEIGHT * LV_DOWNSCALE;
/*Set appearance*/
new_obj_dp->style_p = lv_objs_get(LV_OBJS_DEF, NULL);
new_obj_dp->opa = OPA_COVER;
/*Set virtual functions*/
lv_obj_set_signal_f(new_obj_dp, lv_obj_signal);
lv_obj_set_design_f(new_obj_dp, lv_obj_design);
/*Set attributes*/
new_obj_dp->click_en = 1;
new_obj_dp->drag_en = 0;
new_obj_dp->drag_throw_en = 0;
new_obj_dp->drag_parent = 0;
new_obj_dp->style_iso = 0;
new_obj_dp->hidden = 0;
new_obj_dp->top_en = 0;
new_obj_dp->ext_dp = NULL;
}
if(copy_dp != NULL) {
area_cpy(&new_obj_dp->cords, &copy_dp->cords);
/*Set attributes*/
new_obj_dp->click_en = copy_dp->click_en;
new_obj_dp->drag_en = copy_dp->drag_en;
new_obj_dp->drag_throw_en = copy_dp->drag_throw_en;
new_obj_dp->drag_parent = copy_dp->drag_parent;
new_obj_dp->hidden = copy_dp->hidden;
new_obj_dp->top_en = copy_dp->top_en;
new_obj_dp->style_p = copy_dp->style_p;
if(copy_dp->style_iso != 0) {
lv_obj_iso_style(new_obj_dp, dm_get_size(copy_dp->style_p));
}
lv_obj_set_pos(new_obj_dp, lv_obj_get_x(copy_dp), lv_obj_get_y(copy_dp));
new_obj_dp->opa = copy_dp->opa;
}
/*Send a signal to the parent to notify it about the new child*/
if(parent_dp != NULL) {
parent_dp->signal_f(parent_dp, LV_SIGNAL_CHILD_CHG, new_obj_dp);
/*Invalidate the area if not screen created*/
lv_obj_inv(new_obj_dp);
}
return new_obj_dp;
}
/**
* Delete 'obj_dp' and all of its children
* @param obj_dp
*/
void lv_obj_del(lv_obj_t* obj_dp)
{
lv_obj_inv(obj_dp);
/*Recursively delete the children*/
lv_obj_t* i;
lv_obj_t* i_next;
i = ll_get_head(&(obj_dp->child_ll));
while(i != NULL) {
/*Get the next object before delete this*/
i_next = ll_get_next(&(obj_dp->child_ll), i);
/*Call the recursive del to the child too*/
lv_obj_del(i);
/*Set i to the next node*/
i = i_next;
}
/*Remove the object from parent's children list*/
lv_obj_t* par_dp = lv_obj_get_parent(obj_dp);
if(par_dp == NULL) { /*It is a screen*/
ll_rem(&scr_ll, obj_dp);
} else {
ll_rem(&(par_dp->child_ll), obj_dp);
}
/* All children deleted.
* Now clean up the object specific data*/
obj_dp->signal_f(obj_dp, LV_SIGNAL_CLEANUP, NULL);
/*Delete the base objects*/
if(obj_dp->ext_dp != NULL) dm_free(obj_dp->ext_dp);
if(obj_dp->style_iso != 0) dm_free(obj_dp->style_p);
dm_free(obj_dp); /*Free the object itself*/
/* Reset all display input (dispi) because
* the deleted object can be being pressed*/
lv_dispi_reset();
/*Send a signal to the parent to notify it about the child delete*/
if(par_dp != NULL) {
par_dp->signal_f(par_dp, LV_SIGNAL_CHILD_CHG, NULL);
}
}
/**
* Signal function of the basic object
* @param obj_dp pointer to an object
* @param sign signal type
* @param param parameter for the signal (depends on signal type)
* @return false: the object become invalid (e.g. deleted)
*/
bool lv_obj_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
{
bool valid = true;
switch(sign) {
default:
break;
}
return valid;
}
/**
* Return with a pointer to built-in style and/or copy it to a variable
* @param style a style name from lv_objs_builtin_t enum
* @param copy_p copy the style to this variable. (NULL if unused)
* @return pointer to an lv_objs_t style
*/
lv_objs_t * lv_objs_get(lv_objs_builtin_t style, lv_objs_t * copy_p)
{
lv_objs_t *style_p;
switch(style) {
case LV_OBJS_DEF:
style_p = &lv_objs_def;
break;
case LV_OBJS_COLOR:
style_p = &lv_objs_color;
break;
case LV_OBJS_SCR:
style_p = &lv_objs_scr;
break;
case LV_OBJS_EMPTY:
style_p = &lv_objs_empty;
break;
case LV_OBJS_AUTOCOLOR:
style_p = &lv_objs_autocolor;
break;
default:
style_p = NULL;
}
if(copy_p != NULL) {
if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_objs_t));
else memcpy(copy_p, &lv_objs_def, sizeof(lv_objs_t));
}
return style_p;
}
/*=====================
* Setter functions
*====================*/
/*--------------
* Screen set
*--------------*/
/**
* Load a new screen
* @param scr_dp pointer to a screen
*/
void lv_scr_load(lv_obj_t* scr_dp)
{
act_scr_dp = scr_dp;
lv_obj_inv(act_scr_dp);
}
/*--------------------
* Parent/children set
*--------------------*/
/**
* Set a new parent for an object. Its relative position will be the same.
* @param obj_dp pointer to an object
* @param parent_dp pointer to the new parent object
*/
void lv_obj_set_parent(lv_obj_t* obj_dp, lv_obj_t* parent_dp)
{
lv_obj_inv(obj_dp);
point_t old_pos;
old_pos.x = lv_obj_get_x(obj_dp);
old_pos.y = lv_obj_get_y(obj_dp);
ll_chg_list(&obj_dp->par_dp->child_ll, &parent_dp->child_ll, obj_dp);
obj_dp->par_dp->signal_f(obj_dp->par_dp, LV_SIGNAL_CHILD_CHG, NULL);
obj_dp->par_dp = parent_dp;
lv_obj_set_pos(obj_dp, old_pos.x, old_pos.y);
parent_dp->signal_f(parent_dp, LV_SIGNAL_CHILD_CHG, obj_dp);
lv_obj_inv(obj_dp);
}
/*-------------------------------------------
* Coordinate set (cord_chk_f will be called)
* -----------------------------------------*/
/**
* Set relative the position of an object (relative to the parent)
* @param obj_dp pointer to an object
* @param x new distance from the left side of the parent
* @param y new distance from the top of the parent
*/
void lv_obj_set_pos(lv_obj_t* obj_dp, cord_t x, cord_t y)
{
/*Invalidate the original area*/
lv_obj_inv(obj_dp);
/*Save the original coordinates*/
area_t ori;
lv_obj_get_cords(obj_dp, &ori);
/*Convert x and y to absolute coordinates*/
lv_obj_t* par_dp = obj_dp->par_dp;
x = x + par_dp->cords.x1;
y = y + par_dp->cords.y1;
/*Calculate and set the movement*/
point_t diff;
diff.x = x - obj_dp->cords.x1;
diff.y = y - obj_dp->cords.y1;
obj_dp->cords.x1 += diff.x;
obj_dp->cords.y1 += diff.y;
obj_dp->cords.x2 += diff.x;
obj_dp->cords.y2 += diff.y;
lv_obj_pos_child_refr(obj_dp, diff.x, diff.y);
/*Send a signal*/
obj_dp->signal_f(obj_dp, LV_SIGNAL_CORD_CHG, &ori);
/*Send a signal to the parent too*/
par_dp->signal_f(par_dp, LV_SIGNAL_CHILD_CHG, obj_dp);
/*Invalidate the new area*/
lv_obj_inv(obj_dp);
}
/**
* Set relative the position of an object (relative to the parent).
* The coordinates will be upscaled to compensate LV_DOWNSCALE.
* @param obj_dp pointer to an object
* @param x new distance from the left side of the parent. (will be multiplied with LV_DOWNSCALE)
* @param y new distance from the top of the parent. (will be multiplied with LV_DOWNSCALE)
*/
void lv_obj_set_pos_us(lv_obj_t* obj_dp, cord_t x, cord_t y)
{
lv_obj_set_pos(obj_dp, x * LV_DOWNSCALE, y * LV_DOWNSCALE);
}
/**
* Set the x coordinate of a object
* @param obj_dp pointer to an object
* @param x new distance from the left side from the parent
*/
void lv_obj_set_x(lv_obj_t* obj_dp, cord_t x)
{
lv_obj_set_pos(obj_dp, x, lv_obj_get_y(obj_dp));
}
/**
* Set the x coordinate of a object.
* The coordinate will be upscaled to compensate LV_DOWNSCALE.
* @param obj_dp pointer to an object
* @param x new distance from the left side from the parent. (will be multiplied with LV_DOWNSCALE)
*/
void lv_obj_set_x_us(lv_obj_t* obj_dp, cord_t x)
{
lv_obj_set_pos(obj_dp, x * LV_DOWNSCALE, lv_obj_get_y(obj_dp));
}
/**
* Set the y coordinate of a object
* @param obj_dp pointer to an object
* @param y new distance from the top of the parent
*/
void lv_obj_set_y(lv_obj_t* obj_dp, cord_t y)
{
lv_obj_set_pos(obj_dp, lv_obj_get_x(obj_dp), y);
}
/**
* Set the y coordinate of a object.
* The coordinate will be upscaled to compensate LV_DOWNSCALE.
* @param obj_dp pointer to an object
* @param y new distance from the top of the parent. (will be multiplied with LV_DOWNSCALE)
*/
void lv_obj_set_y_us(lv_obj_t* obj_dp, cord_t y)
{
lv_obj_set_pos(obj_dp, lv_obj_get_x(obj_dp), y * LV_DOWNSCALE);
}
/**
* Set the size of an object
* @param obj_dp pointer to an object
* @param w new width
* @param h new height
*/
void lv_obj_set_size(lv_obj_t* obj_dp, cord_t w, cord_t h)
{
/*Invalidate the original area*/
lv_obj_inv(obj_dp);
/*Save the original coordinates*/
area_t ori;
lv_obj_get_cords(obj_dp, &ori);
//Set the length and height
obj_dp->cords.x2 = obj_dp->cords.x1 + w - 1;
obj_dp->cords.y2 = obj_dp->cords.y1 + h - 1;
/*Send a signal*/
obj_dp->signal_f(obj_dp, LV_SIGNAL_CORD_CHG, &ori);
/*Send a signal to the parent too*/
lv_obj_t* par_dp = lv_obj_get_parent(obj_dp);
if(par_dp != NULL) par_dp->signal_f(par_dp, LV_SIGNAL_CHILD_CHG, obj_dp);
/*Invalidate the new area*/
lv_obj_inv(obj_dp);
}
/**
* Set the size of an object. The coordinates will be upscaled to compensate LV_DOWNSCALE.
* @param obj_dp pointer to an object
* @param w new width (will be multiplied with LV_DOWNSCALE)
* @param h new height (will be multiplied with LV_DOWNSCALE)
*/
void lv_obj_set_size_us(lv_obj_t* obj_dp, cord_t w, cord_t h)
{
lv_obj_set_size(obj_dp, w * LV_DOWNSCALE, h * LV_DOWNSCALE);
}
/**
* Set the width of an object
* @param obj_dp pointer to an object
* @param w new width
*/
void lv_obj_set_width(lv_obj_t* obj_dp, cord_t w)
{
lv_obj_set_size(obj_dp, w, lv_obj_get_height(obj_dp));
}
/**
* Set the width of an object. The width will be upscaled to compensate LV_DOWNSCALE
* @param obj_dp pointer to an object
* @param w new width (will be multiplied with LV_DOWNSCALE)
*/
void lv_obj_set_width_us(lv_obj_t* obj_dp, cord_t w)
{
lv_obj_set_size(obj_dp, w * LV_DOWNSCALE, lv_obj_get_height(obj_dp));
}
/**
* Set the height of an object
* @param obj_dp pointer to an object
* @param h new height
*/
void lv_obj_set_height(lv_obj_t* obj_dp, cord_t h)
{
lv_obj_set_size(obj_dp, lv_obj_get_width(obj_dp), h);
}
/**
* Set the height of an object. The height will be upscaled to compensate LV_DOWNSCALE
* @param obj_dp pointer to an object
* @param h new height (will be multiplied with LV_DOWNSCALE)
*/
void lv_obj_set_height_us(lv_obj_t* obj_dp, cord_t h)
{
lv_obj_set_size(obj_dp, lv_obj_get_width(obj_dp), h * LV_DOWNSCALE);
}
/**
* Align an object to an other object.
* @param obj_dp pointer to an object to align
* @param base_dp pointer to an object (if NULL the parent is used). 'obj_dp' will be aligned to it.
* @param align type of alignment (see 'lv_align_t' enum)
* @param x_mod x coordinate shift after alignment
* @param y_mod y coordinate shift after alignment
*/
void lv_obj_align(lv_obj_t* obj_dp,lv_obj_t* base_dp, lv_align_t align, cord_t x_mod, cord_t y_mod)
{
cord_t new_x = lv_obj_get_x(obj_dp);
cord_t new_y = lv_obj_get_y(obj_dp);
if(base_dp == NULL) {
base_dp = lv_obj_get_parent(obj_dp);
}
switch(align)
{
case LV_ALIGN_CENTER:
new_x = lv_obj_get_width(base_dp) / 2 - lv_obj_get_width(obj_dp) / 2;
new_y = lv_obj_get_height(base_dp) / 2 - lv_obj_get_height(obj_dp) / 2;
break;
case LV_ALIGN_IN_TOP_LEFT:
new_x = 0;
new_y = 0;
break;
case LV_ALIGN_IN_TOP_MID:
new_x = lv_obj_get_width(base_dp) / 2 - lv_obj_get_width(obj_dp) / 2;
new_y = 0;
break;
case LV_ALIGN_IN_TOP_RIGHT:
new_x = lv_obj_get_width(base_dp) - lv_obj_get_width(obj_dp);
new_y = 0;
break;
case LV_ALIGN_IN_BOTTOM_LEFT:
new_x = 0;
new_y = lv_obj_get_height(base_dp) - lv_obj_get_height(obj_dp);
break;
case LV_ALIGN_IN_BOTTOM_MID:
new_x = lv_obj_get_width(base_dp) / 2 - lv_obj_get_width(obj_dp) / 2;
new_y = lv_obj_get_height(base_dp) - lv_obj_get_height(obj_dp);
break;
case LV_ALIGN_IN_BOTTOM_RIGHT:
new_x = lv_obj_get_width(base_dp) - lv_obj_get_width(obj_dp);
new_y = lv_obj_get_height(base_dp) - lv_obj_get_height(obj_dp);
break;
case LV_ALIGN_IN_LEFT_MID:
new_x = 0;
new_y = lv_obj_get_height(base_dp) / 2 - lv_obj_get_height(obj_dp) / 2;
break;
case LV_ALIGN_IN_RIGHT_MID:
new_x = lv_obj_get_width(base_dp) - lv_obj_get_width(obj_dp);
new_y = lv_obj_get_height(base_dp) / 2 - lv_obj_get_height(obj_dp) / 2;
break;
case LV_ALIGN_OUT_TOP_LEFT:
new_x = 0;
new_y = -lv_obj_get_height(obj_dp);
break;
case LV_ALIGN_OUT_TOP_MID:
new_x = lv_obj_get_width(base_dp) / 2 - lv_obj_get_width(obj_dp) / 2;
new_y = - lv_obj_get_height(obj_dp);
break;
case LV_ALIGN_OUT_TOP_RIGHT:
new_x = lv_obj_get_width(base_dp) - lv_obj_get_width(obj_dp);
new_y = - lv_obj_get_height(obj_dp);
break;
case LV_ALIGN_OUT_BOTTOM_LEFT:
new_x = 0;
new_y = lv_obj_get_height(base_dp);
break;
case LV_ALIGN_OUT_BOTTOM_MID:
new_x = lv_obj_get_width(base_dp) / 2 - lv_obj_get_width(obj_dp) / 2;
new_y = lv_obj_get_height(base_dp);
break;
case LV_ALIGN_OUT_BOTTOM_RIGHT:
new_x = lv_obj_get_width(base_dp) - lv_obj_get_width(obj_dp);
new_y = lv_obj_get_height(base_dp);
break;
case LV_ALIGN_OUT_LEFT_TOP:
new_x = - lv_obj_get_width(obj_dp);
new_y = 0;
break;
case LV_ALIGN_OUT_LEFT_MID:
new_x = - lv_obj_get_width(obj_dp);
new_y = lv_obj_get_height(base_dp) / 2 - lv_obj_get_height(obj_dp) / 2;
break;
case LV_ALIGN_OUT_LEFT_BOTTOM:
new_x = - lv_obj_get_width(obj_dp);
new_y = lv_obj_get_height(base_dp) - lv_obj_get_height(obj_dp);
break;
case LV_ALIGN_OUT_RIGHT_TOP:
new_x = lv_obj_get_width(base_dp);
new_y = 0;
break;
case LV_ALIGN_OUT_RIGHT_MID:
new_x = lv_obj_get_width(base_dp);
new_y = lv_obj_get_height(base_dp) / 2 - lv_obj_get_height(obj_dp) / 2;
break;
case LV_ALIGN_OUT_RIGHT_BOTTOM:
new_x = lv_obj_get_width(base_dp);
new_y = lv_obj_get_height(base_dp) - lv_obj_get_height(obj_dp);
break;
}
/*Bring together the coordination system of base_dp and obj_dp*/
lv_obj_t* par_dp = lv_obj_get_parent(obj_dp);
cord_t base_abs_x = base_dp->cords.x1;
cord_t base_abs_y = base_dp->cords.y1;
cord_t par_abs_x = par_dp->cords.x1;
cord_t par_abs_y = par_dp->cords.y1;
new_x -= par_abs_x - base_abs_x;
new_y -= par_abs_y - base_abs_y;
lv_obj_set_pos(obj_dp, new_x + x_mod, new_y + y_mod);
}
/**
* Align an object to an other object. The coordinates will be upscaled to compensate LV_DOWNSCALE.
* @param obj_dp pointer to an object to align
* @param base_dp pointer to an object (if NULL the parent is used). 'obj_dp' will be aligned to it.
* @param align type of alignment (see 'lv_align_t' enum)
* @param x_mod x coordinate shift after alignment (will be multiplied with LV_DOWNSCALE)
* @param y_mod y coordinate shift after alignment (will be multiplied with LV_DOWNSCALE)
*/
void lv_obj_align_us(lv_obj_t* obj_dp,lv_obj_t* base_dp, lv_align_t align, cord_t x_mod, cord_t y_mod)
{
lv_obj_align(obj_dp, base_dp, align, x_mod * LV_DOWNSCALE, y_mod * LV_DOWNSCALE);
}
/*---------------------
* Appearance set
*--------------------*/
/**
* Set a new style for an object
* @param obj_dp pointer to an object
* @param style_p pointer to the new style
*/
void lv_obj_set_style(lv_obj_t* obj_dp, void * style_p)
{
if(obj_dp->style_iso != 0) {
dm_free(obj_dp->style_p);
}
obj_dp->style_p = style_p;
obj_dp->signal_f(obj_dp, LV_SIGNAL_STYLE_CHG, NULL);
lv_obj_inv(obj_dp);
}
/**
* Isolate the style of an object. In other words a unique style will be created
* for this object which can be freely modified independently from the style of the
* other objects.
*/
void * lv_obj_iso_style(lv_obj_t * obj_dp, uint32_t style_size)
{
if(obj_dp->style_iso != 0) return obj_dp->style_p;
void * ori_style_p = lv_obj_get_style(obj_dp);
void * iso_style_dp = dm_alloc(style_size);
dm_assert(iso_style_dp);
memcpy(iso_style_dp, ori_style_p, style_size);
obj_dp->style_iso = 1;
obj_dp->style_p = iso_style_dp;
lv_obj_refr_style(obj_dp);
return obj_dp->style_p;
}
/**
* Set the opacity of an object
* @param obj_dp pointer to an object
* @param opa 0 (transparent) .. 255(fully cover)
*/
void lv_obj_set_opa(lv_obj_t* obj_dp, uint8_t opa)
{
obj_dp->opa = opa;
lv_obj_inv(obj_dp);
}
/**
* Set the opacity of an object and all of its children
* @param obj_dp pointer to an object
* @param opa 0 (transparent) .. 255(fully cover)
*/
void lv_obj_set_opar(lv_obj_t* obj_dp, uint8_t opa)
{
lv_obj_t* i;
LL_READ(obj_dp->child_ll, i) {
lv_obj_set_opar(i, opa);
}
obj_dp->opa = opa;
lv_obj_inv(obj_dp);
}
/*-----------------
* Attribute set
*----------------*/
/**
* Hide an object. It won't be visible and clickable.
* @param obj_dp pointer to an object
* @param hidden_en true: hide the object
*/
void lv_obj_set_hidden(lv_obj_t* obj_dp, bool hidden_en)
{
obj_dp->hidden = hidden_en == false ? 0 : 1;
lv_obj_inv(obj_dp);
}
/**
* Enable or disable the clicking of an object
* @param obj_dp pointer to an object
* @param click_en true: make the object clickable
*/
void lv_obj_set_click(lv_obj_t* obj_dp, bool click_en)
{
obj_dp->click_en = (click_en == true ? 1 : 0);
}
/**
* Enable to bring this object to the foreground if it
* or any of its children is clicked
* @param obj_dp pointer to an object
* @param top_en true: enable the auto top feature
*/
void lv_obj_set_top(lv_obj_t* obj_dp, bool top_en)
{
obj_dp->top_en= (top_en == true ? 1 : 0);
}
/**
* Enable the dragging of an object
* @param obj_dp pointer to an object
* @param drag_en true: make the object dragable
*/
void lv_obj_set_drag(lv_obj_t* obj_dp, bool drag_en)
{
obj_dp->drag_en = (drag_en == true ? 1 : 0);
}
/**
* Enable the throwing of an object after is is dragged
* @param obj_dp pointer to an object
* @param dragthr_en true: enable the drag throw
*/
void lv_obj_set_drag_throw(lv_obj_t* obj_dp, bool dragthr_en)
{
obj_dp->drag_throw_en = (dragthr_en == true ? 1 : 0);
}
/**
* Enable to use parent for drag related operations.
* If trying to drag the object the parent will be moved instead
* @param obj_dp pointer to an object
* @param dragpar_en true: enable the 'drag parent' for the object
*/
void lv_obj_set_drag_parent(lv_obj_t* obj_dp, bool dragpar_en)
{
obj_dp->drag_parent = (dragpar_en == true ? 1 : 0);
}
/**
* Set the signal function of an object.
* Always call the previous signal function in the new.
* @param obj_dp pointer to an object
* @param fp the new signal function
*/
void lv_obj_set_signal_f(lv_obj_t* obj_dp, lv_signal_f_t fp)
{
obj_dp->signal_f = fp;
}
/**
* Set a new design function for an object
* @param obj_dp pointer to an object
* @param fp the new design function
*/
void lv_obj_set_design_f(lv_obj_t* obj_dp, lv_design_f_t fp)
{
obj_dp->design_f = fp;
}
/*----------------
* Other set
*--------------*/
/**
* Allocate a new ext. data for an object
* @param obj_dp pointer to an object
* @param ext_size the size of the new ext. data
* @return Normal pointer to the allocated ext
*/
void * lv_obj_alloc_ext(lv_obj_t* obj_dp, uint16_t ext_size)
{
obj_dp->ext_dp = dm_realloc(obj_dp->ext_dp, ext_size);
return (void*)obj_dp->ext_dp;
}
/**
* Set an application specific number for an object.
* It can help to identify objects in the application.
* @param obj_dp pointer to an object
* @param free_num the new free number
*/
void lv_obj_set_free_num(lv_obj_t* obj_dp, uint8_t free_num)
{
obj_dp->free_num = free_num;
}
#if LV_OBJ_FREE_P != 0
/**
* Set an application specific pointer for an object.
* It can help to identify objects in the application.
* @param obj_dp pointer to an object
* @param free_p the new free pinter
*/
void lv_obj_set_free_p(lv_obj_t* obj_dp, void * free_p)
{
obj_dp->free_p = free_p;
}
#endif
/*=======================
* Getter functions
*======================*/
/*------------------
* Screen get
*-----------------*/
/**
* Return with the actual screen
* @return pointer to to the actual screen object
*/
lv_obj_t* lv_scr_act(void)
{
return act_scr_dp;
}
/**
* Return with the screen of an object
* @param obj_dp pointer to an object
* @return pointer to a screen
*/
lv_obj_t* lv_obj_get_scr(lv_obj_t* obj_dp)
{
lv_obj_t* par_dp = obj_dp;
lv_obj_t* act_p;
do {
act_p = par_dp;
par_dp = lv_obj_get_parent(act_p);
}
while(par_dp != NULL);
return act_p;
}
/*---------------------
* Parent/children get
*--------------------*/
/**
* Returns with the parent of an object
* @param obj_dp pointer to an object
* @return pointer to the parent of 'obj_dp'
*/
lv_obj_t* lv_obj_get_parent(lv_obj_t * obj_dp)
{
return obj_dp->par_dp;
}
/**
* Iterate through the children of an object
* @param obj_dp pointer to an object
* @param child_dp NULL at first call to get the next children
* and the previous return value later
* @return the child after 'act_child_dp' or NULL if no more child
*/
lv_obj_t * lv_obj_get_child(lv_obj_t * obj_dp, lv_obj_t * child_dp)
{
if(child_dp == NULL) {
return ll_get_head(&obj_dp->child_ll);
} else {
return ll_get_next(&obj_dp->child_ll, child_dp);
}
return NULL;
}
/*---------------------
* Coordinate get
*--------------------*/
/**
* Copy the coordinates of an object to an area
* @param obj_dp pointer to an object
* @param cords_p pointer to an area to store the coordinates
*/
void lv_obj_get_cords(lv_obj_t* obj_dp, area_t * cords_p)
{
area_cpy(cords_p, &obj_dp->cords);
}
/**
* Get the x coordinate of object
* @param obj_dp pointer to an object
* @return distance of 'obj_dp' from the left side of its parent
*/
cord_t lv_obj_get_x(lv_obj_t* obj_dp)
{
cord_t rel_x;
lv_obj_t* parent_dp = lv_obj_get_parent(obj_dp);
rel_x = obj_dp->cords.x1 - parent_dp->cords.x1;
return rel_x;
}
/**
* Get the y coordinate of object
* @param obj_dp pointer to an object
* @return distance of 'obj_dp' from the top of its parent
*/
cord_t lv_obj_get_y(lv_obj_t* obj_dp)
{
cord_t rel_y;
lv_obj_t* parent_dp = lv_obj_get_parent(obj_dp);
rel_y = obj_dp->cords.y1 - parent_dp->cords.y1;
return rel_y;
}
/**
* Get the width of an object
* @param obj_dp pointer to an object
* @return the width
*/
cord_t lv_obj_get_width(lv_obj_t* obj_dp)
{
return area_get_width(&obj_dp->cords);
}
/**
* Get the height of an object
* @param obj_dp pointer to an object
* @return the height
*/
cord_t lv_obj_get_height(lv_obj_t* obj_dp)
{
return area_get_height(&obj_dp->cords);
}
/*-----------------
* Appearance get
*---------------*/
/**
* Get the style pointer of an object
* @param obj_dp pointer to an object
* @return pointer to a style
*/
void * lv_obj_get_style(lv_obj_t* obj_dp)
{
return obj_dp->style_p;
}
/**
* Get the opacity of an object
* @param obj_dp pointer to an object
* @return 0 (transparent) .. 255 (fully cover)
*/
opa_t lv_obj_get_opa(lv_obj_t* obj_dp)
{
return obj_dp->opa;
}
/*-----------------
* Attribute get
*----------------*/
/**
* Get the hidden attribute of an object
* @param obj_dp pointer to an object
* @return true: the object is hidden
*/
bool lv_obj_get_hidden(lv_obj_t* obj_dp)
{
return obj_dp->hidden == 0 ? false : true;
}
/**
* Get the click enable attribute of an object
* @param obj_dp pointer to an object
* @return true: the object is clickable
*/
bool lv_obj_get_click(lv_obj_t* obj_dp)
{
return obj_dp->click_en == 0 ? false : true;;
}
/**
* Get the top enable attribute of an object
* @param obj_dp pointer to an object
* @return true: the auto top feture is enabled
*/
bool lv_obj_get_top(lv_obj_t* obj_dp)
{
return obj_dp->top_en == 0 ? false : true;;
}
/**
* Get the drag enable attribute of an object
* @param obj_dp pointer to an object
* @return true: the object is dragable
*/
bool lv_obj_get_drag(lv_obj_t* obj_dp)
{
return obj_dp->drag_en == 0 ? false : true;
}
/**
* Get the drag thow enable attribute of an object
* @param obj_dp pointer to an object
* @return true: drag throw is enabled
*/
bool lv_obj_get_drag_throw(lv_obj_t* obj_dp)
{
return obj_dp->drag_throw_en == 0 ? false : true;
}
/**
* Get the drag parent attribute of an object
* @param obj_dp pointer to an object
* @return true: drag parent is enabled
*/
bool lv_obj_get_drag_parent(lv_obj_t* obj_dp)
{
return obj_dp->drag_parent == 0 ? false : true;
}
/**
* Get the signal function of an object
* @param obj_dp pointer to an object
* @return the signal function
*/
lv_signal_f_t lv_obj_get_signal_f(lv_obj_t* obj_dp)
{
return obj_dp->signal_f;
}
/**
* Get the design function of an object
* @param obj_dp pointer to an object
* @return the design function
*/
lv_design_f_t lv_obj_get_design_f(lv_obj_t* obj_dp)
{
return obj_dp->design_f;
}
/*------------------
* Other get
*-----------------*/
/**
* Get the ext pointer
* @param obj_dp pointer to an object
* @return the ext pointer but not the dynamic version
* Use it as ext->data1, and NOT da(ext)->data1
*/
void * lv_obj_get_ext(lv_obj_t* obj_dp)
{
return obj_dp->ext_dp;
}
/**
* Get the free number
* @param obj_dp pointer to an object
* @return the free number
*/
uint8_t lv_obj_get_free_num(lv_obj_t* obj_dp)
{
return obj_dp->free_num;
}
#if LV_OBJ_FREE_P != 0
/**
* Get the free pointer
* @param obj_dp pointer to an object
* @return the free pointer
*/
void * lv_obj_get_free_p(lv_obj_t* obj_dp)
{
return obj_dp->free_p;
}
#endif
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the base objects.
* @param obj_dp pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* @param return true/false, depends on 'mode'
*/
static bool lv_obj_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode)
{
if(mode == LV_DESIGN_COVER_CHK) {
bool cover;
cover = area_is_in(mask_p, &obj_dp->cords);
return cover;
}
lv_objs_t * objs_p = lv_obj_get_style(obj_dp);
/*Do not draw the empty objects*/
if(objs_p->empty != 0) return true;
opa_t opa = lv_obj_get_opa(obj_dp);
color_t color = objs_p->color;
/*Calculate the color*/
if(objs_p->auto_color != 0) {
lv_obj_t* par_dp = lv_obj_get_parent(obj_dp);
if(par_dp == NULL) { /*If it is a screen use the default color*/
color = LV_OBJ_DEF_SCR_COLOR;
} else { /*Add a random color on every level*/
color = COLOR_WHITE;
while(par_dp != NULL) {
#if COLOR_DEPTH == 1
color.full ++;
#elif COLOR_DEPTH == 8
color.full += 0x52;
#elif COLOR_DEPTH == 16
color.full += 0xA953;
#elif COLOR_DEPTH == 24
color.full +=0x2963A9;
#endif
par_dp = lv_obj_get_parent(par_dp);
}
}
}
/*Simply draw a rectangle*/
#if LV_VDB_SIZE == 0
lv_rfill(&obj_dp->cords, mask_p, color, opa);
#else
lv_vfill(&obj_dp->cords, mask_p, color, opa);
#endif
return true;
}
/**
* Reposition the children of an object. (Called recursively)
* @param obj_dp pointer to an object which children will be repositioned
* @param x_diff x coordinate shift
* @param y_diff y coordinate shift
*/
static void lv_obj_pos_child_refr(lv_obj_t* obj_dp, cord_t x_diff, cord_t y_diff)
{
lv_obj_t* i;
LL_READ(obj_dp->child_ll, i) {
i->cords.x1 += x_diff;
i->cords.y1 += y_diff;
i->cords.x2 += x_diff;
i->cords.y2 += y_diff;
lv_obj_pos_child_refr(i, x_diff, y_diff);
}
}
/**
* Refresh the style of all children of an object. (Called recursively)
* @param style_p refresh objects only with this style. (ignore is if NULL)
* @param obj_dp pointer to an object
*/
static void lv_style_refr_core(void * style_p, lv_obj_t* obj_dp)
{
lv_obj_t* i;
LL_READ(obj_dp->child_ll, i) {
if(i->style_p == style_p || style_p == NULL) {
i->signal_f(i, LV_SIGNAL_STYLE_CHG, NULL);
lv_obj_inv(i);
}
lv_style_refr_core(style_p, i);
}
}
/**
* @file lv_base_obj.h
*
*/
#ifndef LV_OBJ_H
#define LV_OBJ_H
/*********************
* INCLUDES
*********************/
#include <lvgl/lv_misc/2d.h>
#include <stddef.h>
#include <stdbool.h>
#include "misc/mem/dyn_mem.h"
#include "misc/mem/linked_list.h"
#include "misc/others/color.h"
/*********************
* DEFINES
*********************/
/*Error check of lv_conf.h*/
#if LV_HOR_RES == 0 || LV_VER_RES == 0
#error "LV: LV_HOR_RES and LV_VER_RES must be greater then 0"
#endif
#if LV_DOWNSCALE != 1 && LV_DOWNSCALE != 2 && LV_DOWNSCALE != 4
#error "LV: LV_DOWNSCALE can be only 1, 2 or 4"
#endif
#if LV_VDB_SIZE == 0 && (LV_DOWNSCALE != 1 || LV_UPSCALE_MAP != 0 || LV_UPSCALE_FONT != 0 || LV_UPSCALE_STYLE != 0)
#error "LV: If LV_VDB_SIZE == 0 then LV_DOWNSCALE must be 1, LV_UPSCALE_MAP 0, LV_UPSCALE_FONT 0, LV_UPSCALE_STYLE 0"
#endif
/*New defines*/
#if LV_UPSCALE_SYTLE != 0
#define LV_STYLE_MULT LV_DOWNSCALE
#else
#define LV_STYLE_MULT 1
#endif
/**********************
* TYPEDEFS
**********************/
struct __LV_OBJ_T;
typedef enum
{
LV_DESIGN_DRAW,
LV_DESIGN_COVER_CHK,
}lv_design_mode_t;
typedef bool (* lv_design_f_t) (struct __LV_OBJ_T* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
typedef enum
{
LV_SIGNAL_CLEANUP,
LV_SIGNAL_PRESSED,
LV_SIGNAL_PRESS_LOST,
LV_SIGNAL_RELEASED,
LV_SIGNAL_LONG_PRESS,
LV_SIGNAL_DRAG_BEGIN,
LV_SIGNAL_DRAG_END,
LV_SIGNAL_CHILD_CHG,
LV_SIGNAL_CORD_CHG,
LV_SIGNAL_STYLE_CHG,
}lv_signal_t;
typedef bool (* lv_signal_f_t) (struct __LV_OBJ_T* obj_dp, lv_signal_t sign, void * param);
typedef struct __LV_OBJ_T
{
struct __LV_OBJ_T* par_dp;
ll_dsc_t child_ll;
area_t cords;
/*Basic appearance*/
opa_t opa;
/*Attributes and states*/
uint8_t click_en :1; /*1: can be pressed by a display input device*/
uint8_t drag_en :1; /*1: enable the dragging*/
uint8_t drag_throw_en:1; /*1: Enable throwing with drag*/
uint8_t drag_parent :1; /*1. Parent will be dragged instead*/
uint8_t style_iso :1; /*1: The object has got an own style*/
uint8_t hidden :1; /*1: Object is hidden*/
uint8_t top_en :1; /*1: If the object or its children is clicked it goes to the foreground*/
uint8_t res :1;
uint8_t free_num; /*Application specific identifier (set it freely)*/
lv_signal_f_t signal_f;
lv_design_f_t design_f;
void * ext_dp; /*The object attributes can be extended here*/
void * style_p; /*Object specific style*/
#if LV_OBJ_FREE_P != 0
void * free_p; /*Application specific pointer (set it freely)*/
#endif
}lv_obj_t;
typedef enum
{
LV_ALIGN_CENTER = 0,
LV_ALIGN_IN_TOP_LEFT,
LV_ALIGN_IN_TOP_MID,
LV_ALIGN_IN_TOP_RIGHT,
LV_ALIGN_IN_BOTTOM_LEFT,
LV_ALIGN_IN_BOTTOM_MID,
LV_ALIGN_IN_BOTTOM_RIGHT,
LV_ALIGN_IN_LEFT_MID,
LV_ALIGN_IN_RIGHT_MID,
LV_ALIGN_OUT_TOP_LEFT,
LV_ALIGN_OUT_TOP_MID,
LV_ALIGN_OUT_TOP_RIGHT,
LV_ALIGN_OUT_BOTTOM_LEFT,
LV_ALIGN_OUT_BOTTOM_MID,
LV_ALIGN_OUT_BOTTOM_RIGHT,
LV_ALIGN_OUT_LEFT_TOP,
LV_ALIGN_OUT_LEFT_MID,
LV_ALIGN_OUT_LEFT_BOTTOM,
LV_ALIGN_OUT_RIGHT_TOP,
LV_ALIGN_OUT_RIGHT_MID,
LV_ALIGN_OUT_RIGHT_BOTTOM,
}lv_align_t;
typedef struct
{
color_t color;
uint8_t empty :1;
uint8_t auto_color :1;
}lv_objs_t;
typedef enum
{
LV_OBJS_DEF,
LV_OBJS_COLOR,
LV_OBJS_SCR,
LV_OBJS_EMPTY,
LV_OBJS_AUTOCOLOR,
}lv_objs_builtin_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_init(void);
void lv_obj_inv(lv_obj_t* obj_dp);
void lv_obj_refr_style(lv_obj_t* obj_dp);
void lv_style_refr_all(void * style_p);
/*Create and delete*/
lv_obj_t* lv_obj_create(lv_obj_t* parent_dp, lv_obj_t * copy_dp);
void lv_obj_del(lv_obj_t* obj_dp);
/*Virtual functions*/
bool lv_obj_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param);
/*SETTER FUNCTIONS*/
/*Parent/children set*/
void lv_obj_set_parent(lv_obj_t* obj_dp, lv_obj_t* parent_dp);
/*Coordinate set (set_cord_f will be called)*/
void lv_obj_set_pos(lv_obj_t* obj_dp, cord_t x, cord_t y);
void lv_obj_set_pos_us(lv_obj_t* obj_dp, cord_t x, cord_t y);
void lv_obj_set_x(lv_obj_t* obj_dp, cord_t x);
void lv_obj_set_x_us(lv_obj_t* obj_dp, cord_t x);
void lv_obj_set_y(lv_obj_t* obj_dp, cord_t y);
void lv_obj_set_y_us(lv_obj_t* obj_dp, cord_t y);
void lv_obj_set_size(lv_obj_t* obj_dp, cord_t w, cord_t h);
void lv_obj_set_size_us(lv_obj_t* obj_dp, cord_t w, cord_t h);
void lv_obj_set_width(lv_obj_t* obj_dp, cord_t w);
void lv_obj_set_width_us(lv_obj_t* obj_dp, cord_t w);
void lv_obj_set_height(lv_obj_t* obj_dp, cord_t h);
void lv_obj_set_height_us(lv_obj_t* obj_dp, cord_t h);
void lv_obj_align(lv_obj_t* obj_dp,lv_obj_t* base_dp, lv_align_t align, cord_t x_mod, cord_t y_mod);
void lv_obj_align_us(lv_obj_t* obj_dp,lv_obj_t* base_dp, lv_align_t align, cord_t x_mod, cord_t y_mod);
/*Appearance set*/
void lv_obj_set_hidden(lv_obj_t* obj_dp, bool hidden_en);
void lv_obj_set_opa(lv_obj_t* obj_dp, opa_t opa);
void lv_obj_set_opar(lv_obj_t* obj_dp, opa_t opa);
/*Attribute set*/
void lv_obj_set_click(lv_obj_t* obj_dp, bool click_en);
void lv_obj_set_top(lv_obj_t* obj_dp, bool click_en);
void lv_obj_set_drag(lv_obj_t* obj_dp, bool drag_en);
void lv_obj_set_drag_throw(lv_obj_t* obj_dp, bool dragthr_en);
void lv_obj_set_drag_parent(lv_obj_t* obj_dp, bool dragpar_en);
void lv_obj_set_signal_f(lv_obj_t* obj_dp, lv_signal_f_t fp);
void lv_obj_set_design_f(lv_obj_t* obj_dp, lv_design_f_t fp);
/*Other set*/
void * lv_obj_alloc_ext(lv_obj_t* obj_dp, uint16_t ext_size);
void lv_obj_set_style(lv_obj_t* obj_dp, void * style_p);
void * lv_obj_iso_style(lv_obj_t * obj_dp, uint32_t style_size);
void lv_obj_set_free_num(lv_obj_t* obj_dp, uint8_t free_num);
void lv_obj_set_free_p(lv_obj_t* obj_dp, void * free_p);
void lv_obj_merge_style(lv_obj_t* obj_dp);
/*GETTER FUNCTIONS*/
/*Screen get*/
lv_obj_t* lv_scr_act(void);
void lv_scr_load(lv_obj_t* scr_dp);
/*Parent/children get*/
lv_obj_t* lv_obj_get_scr(lv_obj_t* obj_dp);
lv_obj_t* lv_obj_get_parent(lv_obj_t* obj_dp);
lv_obj_t * lv_obj_get_child(lv_obj_t * obj_dp, lv_obj_t * child_dp);
/*Coordinate get*/
void lv_obj_get_cords(lv_obj_t* obj_dp, area_t * cords_p);
cord_t lv_obj_get_x(lv_obj_t* obj_dp);
cord_t lv_obj_get_y(lv_obj_t* obj_dp);
cord_t lv_obj_get_width(lv_obj_t* obj_dp);
cord_t lv_obj_get_height(lv_obj_t* obj_dp);
/*Appearance get*/
bool lv_obj_get_hidden(lv_obj_t* obj_dp);
opa_t lv_obj_get_opa(lv_obj_t* obj_dp);
/*Attribute get*/
bool lv_obj_get_click(lv_obj_t* obj_dp);
bool lv_obj_get_top(lv_obj_t* obj_dp);
bool lv_obj_get_drag(lv_obj_t* obj_dp);
bool lv_obj_get_drag_throw(lv_obj_t* obj_dp);
bool lv_obj_get_drag_parent(lv_obj_t* obj_dp);
/*Virtual functions get*/
lv_design_f_t lv_obj_get_design_f(lv_obj_t* obj_dp);
lv_signal_f_t lv_obj_get_signal_f(lv_obj_t* obj_dp);
/*Other get*/
void * lv_obj_get_ext(lv_obj_t* obj_dp);
void * lv_obj_get_style(lv_obj_t* obj_dp);
uint8_t lv_obj_get_free_num(lv_obj_t* obj_dp);
lv_objs_t * lv_objs_get(lv_objs_builtin_t style, lv_objs_t * copy_p);
/**********************
* MACROS
**********************/
#define LV_SA(obj_dp, style_type) ((style_type *) obj_dp->style_p)
#define LV_EA(obj_dp, obj_type) ((obj_type *) obj_dp->ext_dp)
#endif
/**
* @file lv_refr.c
*
*/
/*********************
* INCLUDES
*********************/
#include <stddef.h>
#include "lv_conf.h"
#include "misc/os/ptask.h"
#include "misc/mem/fifo.h"
#include "lv_refr.h"
#include "lv_vdb.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct
{
area_t area;
uint8_t joined;
}lv_join_t;
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_refr_task(void);
static void lv_refr_join_area(lv_join_t * area_a, uint32_t inv_num);
static void lv_refr_areas(lv_join_t * area_a, uint32_t area_num);
#if LV_VDB_SIZE == 0
static void lv_refr_area_no_vdb(const area_t * area_p);
#else
static void lv_refr_area_with_vdb(const area_t * area_p);
static void lv_refr_area_part_vdb(const area_t * area_p);
#endif
static lv_obj_t* lv_refr_get_top_obj(const area_t * area_p, lv_obj_t* obj_dp);
static void lv_refr_make(lv_obj_t* top_p, const area_t * mask_p);
static void lv_refr_obj(lv_obj_t* obj_dp, const area_t * mask_ori_p);
/**********************
* STATIC VARIABLES
**********************/
fifo_t fifo_inv;
area_t fifo_inv_buf[LV_INV_FIFO_SIZE];
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Initialize the screen refresh subsystem
*/
void lv_refr_init(void)
{
fifo_init(&fifo_inv, fifo_inv_buf, sizeof(area_t), LV_INV_FIFO_SIZE);
ptask_t* task;
task = ptask_create(lv_refr_task, LV_REFR_PERIOD, PTASK_PRIO_MID);
dm_assert(task);
}
/**
* Invalidate an area
* @param area_p pointer to area which should be invalidated
*/
void lv_inv_area(const area_t * area_p)
{
area_t scr_area;
scr_area.x1 = 0;
scr_area.y1 = 0;
scr_area.x2 = LV_HOR_RES - 1;
scr_area.y2 = LV_VER_RES - 1;
area_t com_area;
bool suc;
suc = area_union(&com_area, area_p, &scr_area);
/*The area is truncated to the screen*/
if(suc != false)
{
#if LV_DOWNSCALE == 2
/*Rounding*/
com_area.x1 = com_area.x1 & (~0x1);
com_area.y1 = com_area.y1 & (~0x1);
com_area.x2 = com_area.x2 | 0x1;
com_area.y2 = com_area.y2 | 0x1;
#elif LV_DOWNSCALE == 4
com_area.x1 = com_area.x1 & (~0x3);
com_area.y1 = com_area.y1 & (~0x3);
com_area.x2 = com_area.x2 | 0x3;
com_area.y2 = com_area.y2 | 0x3;
#endif
/*Save the area*/
suc = fifo_push(&fifo_inv, &com_area);
/* There is no place for the new area
* clear the fifo and add the whole screen*/
if(suc == false)
{
fifo_clear(&fifo_inv);
fifo_push(&fifo_inv, &scr_area);
}
}
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Called periodically to handle the refreshing
*/
static void lv_refr_task(void)
{
lv_join_t area_tmp[LV_INV_FIFO_SIZE];
memset(area_tmp, 0, sizeof(area_tmp));
/*Read all data from the fifo_inv*/
uint32_t inv_num;
bool suc;
for(inv_num = 0; inv_num < LV_INV_FIFO_SIZE; inv_num++)
{
suc = fifo_pop(&fifo_inv, &area_tmp[inv_num].area);
if(suc == false) /*Break id the fifo is empty*/
{
break;
}
}
lv_refr_join_area(area_tmp, inv_num);
lv_refr_areas(area_tmp, inv_num);
}
/**
* Join the areas which has got common parts
* @param join_a an array of areas to join
* @param inv_num item number of the array
*/
static void lv_refr_join_area(lv_join_t * area_a, uint32_t area_num)
{
uint32_t join_from;
uint32_t join_in;
area_t joined_area;
for(join_in = 0; join_in < area_num; join_in++) {
if(area_a[join_in].joined != 0) continue;
/*Check all areas to join them in 'join_in'*/
for(join_from = 0; join_from < area_num; join_from++) {
/*Handle only unjoined areas and ignore itself*/
if(area_a[join_from].joined != 0 || join_in == join_from) {
continue;
}
/*Check if the areas are on each other*/
if(area_is_on(&area_a[join_in].area,
&area_a[join_from].area) == false)
{
continue;
}
area_join(&joined_area, &area_a[join_in].area,
&area_a[join_from].area);
/*Join two area only if the joined area size is smaller*/
if(area_get_size(&joined_area) <
(area_get_size(&area_a[join_in].area) + area_get_size(&area_a[join_from].area))) {
area_cpy(&area_a[join_in].area, &joined_area);
/*Mark 'join_form' is joined into 'join_in'*/
area_a[join_from].joined = 1;
}
}
}
}
/**
* Refresh the joined areas
* @param area_a array of joined invalid areas
* @param area_num item number of the array
*/
static void lv_refr_areas(lv_join_t * area_a, uint32_t area_num)
{
uint32_t i;
for(i = 0; i < area_num; i++) {
/*Refresh the unjoined areas*/
if(area_a[i].joined == 0) {
/*If there is no VDB do simple drawing*/
#if LV_VDB_SIZE == 0
lv_refr_area_no_vdb(&area_a[i].area);
#else
/*If VDB is used...*/
lv_refr_area_with_vdb(&area_a[i].area);
#endif
}
}
}
#if LV_VDB_SIZE == 0
/**
* Refresh an area if there is no Virtual Display Buffer
* @param area_p pointer to an area to refresh
*/
static void lv_refr_area_no_vdb(const area_t * area_p)
{
lv_obj_t* top_p;
/*Get top object which is not covered by others*/
top_p = lv_refr_get_top_obj(area_p, lv_scr_act());
/*Do the refreshing*/
lv_refr_make(top_p, area_p);
}
#else
/**
* Refresh an area if there is Virtual Display Buffer
* @param area_p pointer to an area to refresh
*/
static void lv_refr_area_with_vdb(const area_t * area_p)
{
lv_vdb_t * vdb_p = lv_vdb_get();
/*Always use the full row*/
vdb_p->vdb_area.x1 = area_p->x1;
vdb_p->vdb_area.y1 = area_p->y1;
vdb_p->vdb_area.x2 = area_p->x2;
/*Calculate the max row num*/
uint32_t max_row = (uint32_t) LV_VDB_SIZE / (vdb_p->vdb_area.x2 - vdb_p->vdb_area.x1 + 1);
if(max_row > area_get_height(area_p)) max_row = area_get_height(area_p);
/*Round the row number with downscale*/
#if LV_DOWNSCALE == 2
max_row &= (~0x1);
#elif LV_DOWNSCALE == 4
max_row &= (~0x3);
#endif
/*Refresh all rows*/
cord_t row = area_p->y1;
for(row = area_p->y1; row + max_row - 1 <= area_p->y2; row += max_row) {
/*Calc. the next y coordinates of VDB*/
vdb_p->vdb_area.y1 = row;
vdb_p->vdb_area.y2 = row + max_row - 1;
lv_refr_area_part_vdb(area_p);
}
/*If the last y coordinates are not handled yet ...*/
if(area_p->y2 != vdb_p->vdb_area.y2) {
/*Calc. the next y coordinates of VDB*/
vdb_p->vdb_area.y1 = row;
vdb_p->vdb_area.y2 = area_p->y2;
/*Refresh this part too*/
lv_refr_area_part_vdb(area_p);
}
}
/**
* Refresh a part of an area which is on the actual Virtual Display Buffer
* @param area_p pointer to an area to refresh
*/
static void lv_refr_area_part_vdb(const area_t * area_p)
{
lv_vdb_t * vdb_p = lv_vdb_get();
lv_obj_t* top_p;
/*Get the new mask from the original area and the act. VDB
It will be a part of 'area_p'*/
area_t start_mask;
area_union(&start_mask, area_p, &vdb_p->vdb_area);
/*Get the most top object which is not covered by others*/
top_p = lv_refr_get_top_obj(&start_mask, lv_scr_act());
/*Do the refreshing*/
lv_refr_make(top_p, &start_mask);
/*Flush the content of the VDB*/
lv_vdb_flush();
}
#endif /*LV_VDB_SIZE == 0*/
/**
* Search the most top object which fully covers an area
* @param area_p pointer to an area
* @param obj_dp the first object to start the searching (typically a screen)
* @return
*/
static lv_obj_t* lv_refr_get_top_obj(const area_t * area_p, lv_obj_t* obj_dp)
{
lv_obj_t* i;
lv_obj_t* found_p = NULL;
/*If this object is fully cover the draw area check the children too */
if(obj_dp->opa == OPA_COVER &&
obj_dp->hidden == 0 &&
obj_dp->design_f(obj_dp, area_p, LV_DESIGN_COVER_CHK) != false)
{
LL_READ(obj_dp->child_ll, i) {
found_p = lv_refr_get_top_obj(area_p, i);
/*If a children is ok then break*/
if(found_p != NULL) {
break;
}
}
/*If there is no better children use this object*/
if(found_p == NULL) {
found_p = obj_dp;
}
}
return found_p;
}
/**
* Make the refreshing from an object. Draw all its children and the yungers too.
* @param top_p pointer to an objects. Start the drawing from it.
* @param mask_p pointer to an area, the objects will be drawn only here
*/
static void lv_refr_make(lv_obj_t* top_p, const area_t * mask_p)
{
/* Normally always will be a top_obj (at least the screen)
* but in special cases (e.g. if the screen has alpha) it won't.
* In this case use the screen directly */
if(top_p == NULL) top_p = lv_scr_act();
/*Refresh the top object and its children*/
lv_refr_obj(top_p, mask_p);
/*Draw the 'younger' objects because they can be on top_obj */
lv_obj_t* par_dp;
lv_obj_t* i;
lv_obj_t* border_p = top_p;
par_dp = lv_obj_get_parent(top_p);
/*Do until not reach the screen*/
while(par_dp != NULL) {
/*object before border_p has to be redrawn*/
i = ll_get_prev(&(par_dp->child_ll), border_p);
while(i != NULL) {
/*Refresh the objects*/
lv_refr_obj(i, mask_p);
i = ll_get_prev(&(par_dp->child_ll), i);
}
/*The new border will be there last parents,
*so the 'younger' brothers of parent will be refreshed*/
border_p = par_dp;
/*Go a level deeper*/
par_dp = lv_obj_get_parent(par_dp);
}
}
/**
* Refresh an object an all of its children. (Called recursively)
* @param obj_dp pointer to an object to refresh
* @param mask_ori_p pointer to an area, the objects will be drawn only here
*/
static void lv_refr_obj(lv_obj_t* obj_dp, const area_t * mask_ori_p)
{
/*Do not refresh hidden objects*/
if(obj_dp->hidden != 0) return;
bool union_ok; /* Store the return value of area_union */
/* Truncate the original mask to the coordinates of the parent
* because the parent and its children are visible only here */
area_t mask_parent;
union_ok = area_union(&mask_parent, mask_ori_p, &obj_dp->cords);
/*Draw the parent and its children only if they ore on 'mask_parent'*/
if(union_ok != false) {
/* Redraw the object */
if(obj_dp->opa != OPA_TRANSP) {
obj_dp->design_f(obj_dp, &mask_parent, LV_DESIGN_DRAW);
}
area_t mask_child; /*Mask from obj_dp and its child*/
lv_obj_t* child_p;
LL_READ_BACK(obj_dp->child_ll, child_p)
{
/* Get the union (common parts) of original mask (from obj_dp)
* and its child */
union_ok = area_union(&mask_child, &mask_parent, &child_p->cords);
/*If the parent and the child has common area then refresh the child */
if(union_ok) {
/*Refresh the next children*/
lv_refr_obj(child_p, &mask_child);
}
}
}
}
/**
* @file lv_refr.h
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_obj.h"
#include <stdbool.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_refr_init(void);
void lv_inv_area(const area_t * area_p);
/**********************
* STATIC FUNCTIONS
**********************/
\ No newline at end of file
/**
* @file lv_vdb.c
*
*/
#include "../../lv_conf.h"
#if LV_VDB_SIZE != 0
#include "hal/disp/disp.h"
#include <stddef.h>
#include "lv_vdb.h"
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
static lv_vdb_t vdb;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Get the vdb variable
* @return pointer to the vdb variable
*/
lv_vdb_t * lv_vdb_get(void)
{
return &vdb;
}
/**
* Flush the content of the vdb
*/
void lv_vdb_flush(void)
{
#if LV_DOWNSCALE < 2
disp_area(DISP_ID_ALL, vdb.vdb_area.x1 , vdb.vdb_area.y1, vdb.vdb_area.x2, vdb.vdb_area.y2);
disp_map(DISP_ID_ALL, vdb.buf);
#elif LV_DOWNSCALE == 2
color_t row_buf[LV_HOR_RES / LV_DOWNSCALE];
color_t * row_buf_p;
cord_t x;
cord_t y;
cord_t w = area_get_width(&vdb.vdb_area);
cord_t i;
color_t * buf_p = vdb.buf;
for(y = vdb.vdb_area.y1 >> 1; y <= vdb.vdb_area.y2 >> 1; y ++) {
i = 0;
row_buf_p = row_buf;
for(x = vdb.vdb_area.x1; x < vdb.vdb_area.x2; x += 2, i += 2) {
row_buf_p->red = (buf_p[i].red +
buf_p[i + 1].red +
buf_p[i + w].red +
buf_p[i + w + 1].red) >> 2;
row_buf_p->green = (buf_p[i].green +
buf_p[i + 1].green +
buf_p[i + w].green +
buf_p[i + w + 1].green) >> 2;
row_buf_p->blue = (buf_p[i].blue +
buf_p[i + 1].blue +
buf_p[i + w].blue +
buf_p[i + w + 1].blue) >> 2;
row_buf_p++;
}
buf_p += LV_DOWNSCALE * w;
disp_area(DISP_ID_ALL, vdb.vdb_area.x1 >> 1, y, vdb.vdb_area.x2 >> 1, y);
disp_map(DISP_ID_ALL, row_buf);
}
#elif LV_DOWNSCALE == 4
color_t row_buf[LV_HOR_RES / LV_DOWNSCALE];
color_t * row_buf_p;
cord_t x;
cord_t y;
cord_t w = area_get_width(&vdb.vdb_area);
cord_t i;
color_t * buf_p = vdb.buf;
for(y = vdb.vdb_area.y1 >> 2; y <= vdb.vdb_area.y2 >> 2; y ++) {
i = 0;
row_buf_p = row_buf;
for(x = vdb.vdb_area.x1; x < vdb.vdb_area.x2; x += 4, i += 4) {
row_buf_p->red = (buf_p[i].red + buf_p[i + 1].red +
buf_p[i + 2].red + buf_p[i + 3].red +
buf_p[i + w].red + buf_p[i + w + 1].red +
buf_p[i + w + 2].red + buf_p[i + w + 3].red +
buf_p[i + 2 * w].red + buf_p[i + 2 * w + 1].red +
buf_p[i + 2 * w + 2].red + buf_p[i + 2 * w + 3].red +
buf_p[i + 3 * w].red + buf_p[i + 3 * w + 1].red +
buf_p[i + 3 * w + 2].red + buf_p[i + 3 * w + 3].red) >>4 ;
row_buf_p->green = (buf_p[i].green + buf_p[i + 1].green +
buf_p[i + 2].green + buf_p[i + 3].green +
buf_p[i + w].green + buf_p[i + w + 1].green +
buf_p[i + w + 2].green + buf_p[i + w + 3].green +
buf_p[i + 2 * w].green + buf_p[i + 2 * w + 1].green +
buf_p[i + 2 * w + 2].green + buf_p[i + 2 * w + 3].green +
buf_p[i + 3 * w].green + buf_p[i + 3 * w + 1].green +
buf_p[i + 3 * w + 2].green + buf_p[i + 3 * w + 3].green) >>4 ;
row_buf_p->blue = (buf_p[i].blue + buf_p[i + 1].blue +
buf_p[i + 2].blue + buf_p[i + 3].blue +
buf_p[i + w].blue + buf_p[i + w + 1].blue +
buf_p[i + w + 2].blue + buf_p[i + w + 3].blue +
buf_p[i + 2 * w].blue + buf_p[i + 2 * w + 1].blue +
buf_p[i + 2 * w + 2].blue + buf_p[i + 2 * w + 3].blue +
buf_p[i + 3 * w].blue + buf_p[i + 3 * w + 1].blue +
buf_p[i + 3 * w + 2].blue + buf_p[i + 3 * w + 3].blue) >>4 ;
row_buf_p++;
}
buf_p += LV_DOWNSCALE * w;
disp_area(DISP_ID_ALL, vdb.vdb_area.x1 >> 2, y, vdb.vdb_area.x2 >> 2, y);
disp_map(DISP_ID_ALL, row_buf);
}
#else
#error "LV: Not supported LV_DOWNSCALE"
#endif
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif
/**
* @file lv_vdb.h
*
*/
#ifndef LV_VDB_H
#define LV_VDB_H
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if LV_VDB_SIZE != 0
#include "misc/others/color.h"
#include <lvgl/lv_misc/2d.h>
#include "../lv_misc/font.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct
{
area_t vdb_area;
color_t buf[LV_VDB_SIZE];
}lv_vdb_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_vdb_t * lv_vdb_get(void);
void lv_vdb_flush(void);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file lv_btn.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#if USE_LV_BTN != 0
#include <string.h>
#include "lv_btn.h"
#include "../lv_draw/lv_draw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool lv_btn_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
/**********************
* STATIC VARIABLES
**********************/
/*-----------------
* Style definition
*-----------------*/
static lv_btns_t lv_btns_def =
{
.rel.mcolor = COLOR_MAKE(0x40, 0x60, 0x80), .rel.gcolor = COLOR_BLACK,
.rel.bcolor = COLOR_WHITE, .rel.bwidth = 2 * LV_STYLE_MULT, .rel.bopa = 50,
.rel.round = 4 * LV_STYLE_MULT, .rel.empty = 0,
.pr.mcolor = COLOR_MAKE(0x60, 0x80, 0xa0), .pr.gcolor = COLOR_MAKE(0x20, 0x30, 0x40),
.pr.bcolor = COLOR_WHITE, .pr.bwidth = 2 * LV_STYLE_MULT, .pr.bopa = 50,
.pr.round = 4 * LV_STYLE_MULT, .pr.empty = 0,
.tgl_rel.mcolor = COLOR_MAKE(0x80,0x00,0x00), .tgl_rel.gcolor = COLOR_MAKE(0x20, 0x20, 0x20),
.tgl_rel.bcolor = COLOR_WHITE, .tgl_rel.bwidth = 2 * LV_STYLE_MULT, .tgl_rel.bopa = 50,
.tgl_rel.round = 4 * LV_STYLE_MULT, .tgl_rel.empty = 0,
.tgl_pr.mcolor = COLOR_MAKE(0xf0, 0x26, 0x26), .tgl_pr.gcolor = COLOR_MAKE(0x40, 0x40, 0x40),
.tgl_pr.bcolor = COLOR_WHITE, .tgl_pr.bwidth = 2 * LV_STYLE_MULT, .tgl_pr.bopa = 50,
.tgl_pr.round = 4 * LV_STYLE_MULT, .tgl_pr.empty = 0,
.ina.mcolor = COLOR_SILVER, .ina.gcolor = COLOR_GRAY,
.ina.bcolor = COLOR_WHITE, .ina.bwidth = 2 * LV_STYLE_MULT, .ina.bopa = 50,
.ina.round = 4 * LV_STYLE_MULT, .ina.empty = 0,
};
static lv_btns_t lv_btns_transp =
{
.rel.bwidth = 0, .rel.empty = 1, .rel.round = 0,
.pr.bwidth = 0, .pr.empty = 1, .rel.round = 0,
.tgl_rel.bwidth = 0, .tgl_rel.empty = 1, .rel.round = 0,
.tgl_pr.bwidth = 0, .tgl_pr.empty = 1, .rel.round = 0,
.ina.bwidth = 0, .ina.empty = 1, .rel.round = 0,
};
static lv_btns_t lv_btns_border =
{
.rel.bcolor = COLOR_BLACK, .rel.bwidth = 2 * LV_STYLE_MULT, .rel.bopa = 100,
.rel.round = 4 * LV_STYLE_MULT, .rel.empty = 1,
.pr.bcolor = COLOR_GRAY, .pr.bwidth = 2 * LV_STYLE_MULT, .pr.bopa = 100,
.pr.round = 4 * LV_STYLE_MULT, .pr.empty = 1,
.tgl_rel.bcolor = COLOR_SILVER, .tgl_rel.bwidth = 2 * LV_STYLE_MULT, .tgl_rel.bopa = 100,
.tgl_rel.round = 4 * LV_STYLE_MULT, .tgl_rel.empty = 1,
.tgl_pr.bcolor = COLOR_GRAY, .tgl_pr.bwidth = 2 * LV_STYLE_MULT, .tgl_pr.bopa = 100,
.tgl_pr.round = 4 * LV_STYLE_MULT, .tgl_pr.empty = 1,
.ina.bcolor = COLOR_GRAY, .ina.bwidth = 2 * LV_STYLE_MULT, .ina.bopa = 100,
.ina.round = 4 * LV_STYLE_MULT, .ina.empty = 1,
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Create a button objects
* @param par_dp pointer to an object, it will be the parent of the new button
* @param copy_dp pointer to a button object, if not NULL then the new object will be copied from it
* @return pointer to the created button
*/
lv_obj_t* lv_btn_create(lv_obj_t* par_dp, lv_obj_t * copy_dp)
{
lv_obj_t* new_obj;
new_obj = lv_obj_create(par_dp, copy_dp);
/*Allocate the extended data*/
lv_obj_alloc_ext(new_obj, sizeof(lv_btn_ext_t));
lv_obj_set_signal_f(new_obj, lv_btn_signal);
lv_obj_set_design_f(new_obj, lv_btn_design);
lv_btn_ext_t * btn_ext_dp = lv_obj_get_ext(new_obj);
btn_ext_dp->lpr_exec = 0;
/*If no copy do the basic initialization*/
if(copy_dp == NULL)
{
btn_ext_dp->state = LV_BTN_REL;
btn_ext_dp->pr_action = NULL;
btn_ext_dp->rel_action = NULL;
btn_ext_dp->lpr_action = NULL;
btn_ext_dp->tgl = 0;
lv_obj_set_style(new_obj, &lv_btns_def);
}
/*Copy 'copy_dp'*/
else{
lv_btn_ext_t * ori_btnd_dp = lv_obj_get_ext(copy_dp);
btn_ext_dp->state = ori_btnd_dp->state;
btn_ext_dp->pr_action = ori_btnd_dp->pr_action;
btn_ext_dp->rel_action = ori_btnd_dp->rel_action;
btn_ext_dp->lpr_action = ori_btnd_dp->lpr_action;
btn_ext_dp->tgl = ori_btnd_dp->tgl;
}
return new_obj;
}
/**
* Signal function of the button
* @param obj_dp pointer to a button object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
*/
bool lv_btn_signal(lv_obj_t * obj_dp, lv_signal_t sign, void* param)
{
bool valid;
/* Include the ancient signal function */
valid = lv_obj_signal(obj_dp, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
lv_btn_state_t state = lv_btn_get_state(obj_dp);
lv_btn_ext_t * btn_ext_dp = lv_obj_get_ext(obj_dp);
bool tgl = lv_btn_get_tgl(obj_dp);
switch (sign){
case LV_SIGNAL_PRESSED:
/*Refresh the state*/
if(btn_ext_dp->state == LV_BTN_REL) {
btn_ext_dp->state = LV_BTN_PR;
} else if(btn_ext_dp->state == LV_BTN_TGL_REL) {
btn_ext_dp->state = LV_BTN_TGL_PR;
}
lv_obj_inv(obj_dp);
btn_ext_dp->lpr_exec = 0;
/*Call the press action, here 'param' is the caller dispi*/
if(btn_ext_dp->pr_action != NULL && state != LV_BTN_INA) {
valid = btn_ext_dp->pr_action(obj_dp, param);
}
break;
case LV_SIGNAL_PRESS_LOST:
/*Refresh the state*/
if(btn_ext_dp->state == LV_BTN_PR) {
btn_ext_dp->state = LV_BTN_REL;
} else if(btn_ext_dp->state == LV_BTN_TGL_PR) {
btn_ext_dp->state = LV_BTN_TGL_REL;
}
lv_obj_inv(obj_dp);
break;
case LV_SIGNAL_RELEASED:
/*If not dragged and it was not long press action then
*change state and run the action*/
if(lv_dispi_is_dragging(param) == false && btn_ext_dp->lpr_exec == 0) {
if(btn_ext_dp->state == LV_BTN_PR && tgl == false) {
btn_ext_dp->state = LV_BTN_REL;
} else if(btn_ext_dp->state == LV_BTN_TGL_PR && tgl == false) {
btn_ext_dp->state = LV_BTN_TGL_REL;
} else if(btn_ext_dp->state == LV_BTN_PR && tgl == true) {
btn_ext_dp->state = LV_BTN_TGL_REL;
} else if(btn_ext_dp->state == LV_BTN_TGL_PR && tgl == true) {
btn_ext_dp->state = LV_BTN_REL;
}
if(btn_ext_dp->rel_action != NULL && state != LV_BTN_INA) {
valid = btn_ext_dp->rel_action(obj_dp, param);
}
} else { /*If dragged change back the state*/
if(btn_ext_dp->state == LV_BTN_PR) {
btn_ext_dp->state = LV_BTN_REL;
} else if(btn_ext_dp->state == LV_BTN_TGL_PR) {
btn_ext_dp->state = LV_BTN_TGL_REL;
}
}
lv_obj_inv(obj_dp);
break;
case LV_SIGNAL_LONG_PRESS:
/*Call the long press action, here 'param' is the caller dispi*/
if(btn_ext_dp->lpr_action != NULL && state != LV_BTN_INA) {
btn_ext_dp->lpr_exec = 1;
valid = btn_ext_dp->lpr_action(obj_dp, param);
}
break;
default:
/*Do nothing*/
break;
}
}
return valid;
}
/*=====================
* Setter functions
*====================*/
/**
* Enable the toggled states
* @param obj_dp pointer to a button object
* @param tgl true: enable toggled states, false: disable
*/
void lv_btn_set_tgl(lv_obj_t* obj_dp, bool tgl)
{
lv_btn_ext_t * btn_p = lv_obj_get_ext(obj_dp);
btn_p->tgl = tgl != false ? 1 : 0;
}
/**
* Set the state of the button
* @param obj_dp pointer to a button object
* @param state the new state of the button (from lv_btn_state_t enum)
*/
void lv_btn_set_state(lv_obj_t* obj_dp, lv_btn_state_t state)
{
lv_btn_ext_t * btn_p = lv_obj_get_ext(obj_dp);
btn_p->state = state;
lv_obj_inv(obj_dp);
}
/**
* Set a function to call when the button is pressed
* @param obj_dp pointer to a button object
* @param pr_action pointer to function
*/
void lv_btn_set_pr_action(lv_obj_t* obj_dp, bool (*pr_action)(lv_obj_t*, lv_dispi_t *))
{
lv_btn_ext_t * btn_p = lv_obj_get_ext(obj_dp);
btn_p->pr_action = pr_action;
}
/**
* Set a function to call when the button is released
* @param obj_dp pointer to a button object
* @param pr_action pointer to function
*/
void lv_btn_set_rel_action(lv_obj_t* obj_dp, bool (*rel_action)(lv_obj_t*, lv_dispi_t *))
{
lv_btn_ext_t * btn_p = lv_obj_get_ext(obj_dp);
btn_p->rel_action = rel_action;
}
/**
* Set a function to call when the button is long pressed
* @param obj_dp pointer to a button object
* @param pr_action pointer to function
*/
void lv_btn_set_lpr_action(lv_obj_t* obj_dp, bool (*lpr_action)(lv_obj_t*, lv_dispi_t *))
{
lv_btn_ext_t * btn_p = lv_obj_get_ext(obj_dp);
btn_p->lpr_action = lpr_action;
}
/*=====================
* Getter functions
*====================*/
/**
* Get the current state of the button
* @param obj_dp pointer to a button object
* @return the state of the button (from lv_btn_state_t enum)
*/
lv_btn_state_t lv_btn_get_state(lv_obj_t* obj_dp)
{
lv_btn_ext_t * btn_p = lv_obj_get_ext(obj_dp);
return btn_p->state;
}
/**
* Get the toggle enable attribute of the button
* @param obj_dp pointer to a button object
* @return ture: toggle enabled, false: disabled
*/
bool lv_btn_get_tgl(lv_obj_t* obj_dp)
{
lv_btn_ext_t * btn_p = lv_obj_get_ext(obj_dp);
return btn_p->tgl != 0 ? true : false;
}
/**
* Return with a pointer to a built-in style and/or copy it to a variable
* @param style a style name from lv_btns_builtin_t enum
* @param copy_p copy the style to this variable. (NULL if unused)
* @return pointer to an lv_btns_t style
*/
lv_btns_t * lv_btns_get(lv_btns_builtin_t style, lv_btns_t * copy_p)
{
lv_btns_t *style_p;
switch(style) {
case LV_BTNS_DEF:
style_p = &lv_btns_def;
break;
case LV_BTNS_TRANSP:
style_p = &lv_btns_transp;
break;
case LV_BTNS_BORDER:
style_p = &lv_btns_border;
break;
default:
style_p = NULL;
}
if(copy_p != NULL) {
if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_btns_t));
else memcpy(copy_p, &lv_btns_def, sizeof(lv_btns_t));
}
return style_p;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the buttons
* @param obj_dp pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* @param return true/false, depends on 'mode'
*/
static bool lv_btn_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode)
{
lv_btns_t * btns_p = lv_obj_get_style(obj_dp);
lv_rects_t * rects_p;
switch(lv_btn_get_state(obj_dp)) {
case LV_BTN_REL:
rects_p = &btns_p->rel;
break;
case LV_BTN_PR:
rects_p = &btns_p->pr;
break;
case LV_BTN_TGL_PR:
rects_p = &btns_p->tgl_pr;
break;
case LV_BTN_TGL_REL:
rects_p = &btns_p->tgl_rel;
break;
case LV_BTN_INA:
rects_p = &btns_p->ina;
break;
default:
rects_p = &btns_p->rel;
break;
}
/* Because of the radius it is not sure the area is covered*/
if(mode == LV_DESIGN_COVER_CHK) {
uint16_t r = rects_p->round;
area_t area_tmp;
/*Check horizontally without radius*/
lv_obj_get_cords(obj_dp, &area_tmp);
area_tmp.x1 += r;
area_tmp.x2 -= r;
if(area_is_in(mask_p, &area_tmp) == true) return true;
/*Check vertically without radius*/
lv_obj_get_cords(obj_dp, &area_tmp);
area_tmp.y1 += r;
area_tmp.y2 -= r;
if(area_is_in(mask_p, &area_tmp) == true) return true;
return false;
}
opa_t opa = lv_obj_get_opa(obj_dp);
area_t area;
lv_obj_get_cords(obj_dp, &area);
/*Draw the rectangle*/
lv_draw_rect(&area, mask_p, rects_p, opa);
return true;
}
#endif
/**
* @file lv_btn.h
*
*/
#ifndef LV_BTN_H
#define LV_BTN_H
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if USE_LV_BTN != 0
#include "lv_rect.h"
#include "../lv_obj/lv_dispi.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum
{
LV_BTN_PR,
LV_BTN_REL,
LV_BTN_TGL_PR,
LV_BTN_TGL_REL,
LV_BTN_INA,
}lv_btn_state_t;
typedef struct
{
lv_rects_t rel;
lv_rects_t pr;
lv_rects_t tgl_rel;
lv_rects_t tgl_pr;
lv_rects_t ina;
}lv_btns_t;
typedef enum
{
LV_BTNS_DEF,
LV_BTNS_TRANSP,
LV_BTNS_BORDER,
}lv_btns_builtin_t;
typedef struct
{
bool (*pr_action)(lv_obj_t*, lv_dispi_t *);
bool (*rel_action)(lv_obj_t*, lv_dispi_t *);
bool (*lpr_action)(lv_obj_t*, lv_dispi_t *);
lv_btn_state_t state;
uint8_t tgl :1; /*1: Toggle enabled*/
uint8_t lpr_exec :1; /*1: long press action executed (Not for user)*/
}lv_btn_ext_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*Create function*/
lv_obj_t* lv_btn_create(lv_obj_t* par_dp, lv_obj_t * c_dp);
bool lv_btn_signal(lv_obj_t * obj_dp, lv_signal_t sign, void * param);
lv_btns_t * lv_btns_get(lv_btns_builtin_t style, lv_btns_t * copy_p);
void lv_btn_set_tgl(lv_obj_t* obj_dp, bool tgl);
void lv_btn_set_state(lv_obj_t* obj_dp, lv_btn_state_t state);
void lv_btn_set_pr_action(lv_obj_t* obi_p, bool (*pr_action)(lv_obj_t*, lv_dispi_t *));
void lv_btn_set_rel_action(lv_obj_t* obj_dp, bool (*rel_action)(lv_obj_t*, lv_dispi_t *));
void lv_btn_set_lpr_action(lv_obj_t* obj_dp, bool (*lpr_action)(lv_obj_t*, lv_dispi_t *));
bool lv_btn_get_tgl(lv_obj_t* obj_dp);
lv_btn_state_t lv_btn_get_state(lv_obj_t* obj_dp);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file lv_img.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if USE_LV_IMG != 0
#include "lv_img.h"
#include "../lv_draw/lv_draw.h"
#include "misc/fs/fsint.h"
#include "misc/fs/ufs/ufs.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool lv_img_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
/**********************
* STATIC VARIABLES
**********************/
/*-----------------
* Style definition
*-----------------*/
static lv_imgs_t lv_imgs_def = {.transp_en = 0};
static lv_imgs_t lv_imgs_transp = {.transp_en = 1};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Create an image objects
* @param par_dp pointer to an object, it will be the parent of the new button
* @param copy_dp pointer to a rectangle object, if not NULL then the new object will be copied from it
* @return pointer to the created image
*/
lv_obj_t* lv_img_create(lv_obj_t* par_dp, lv_obj_t * copy_dp)
{
lv_obj_t* new_obj_dp = NULL;
/*Create a basic object*/
new_obj_dp = lv_obj_create(par_dp, NULL);
/*Extend the basic object to image object*/
lv_obj_alloc_ext(new_obj_dp, sizeof(lv_img_ext_t));
/*Init the new object*/
lv_obj_set_signal_f(new_obj_dp, lv_img_signal);
lv_obj_set_design_f(new_obj_dp, lv_img_design);
lv_img_ext_t * img_ext_dp = lv_obj_get_ext(new_obj_dp);
if(copy_dp == NULL) {
img_ext_dp->fn_dp = NULL;
img_ext_dp->w = lv_obj_get_width(new_obj_dp);
img_ext_dp->h = lv_obj_get_height(new_obj_dp);
if(par_dp != NULL) {
img_ext_dp->auto_size = 1;
} else {
img_ext_dp->auto_size = 0;
}
lv_obj_set_style(new_obj_dp, &lv_imgs_def);
} else {
img_ext_dp->auto_size = LV_EA(copy_dp, lv_img_ext_t)->auto_size;
lv_img_set_file(new_obj_dp, LV_EA(copy_dp, lv_img_ext_t)->fn_dp);
}
return new_obj_dp;
}
/**
* Signal function of the image
* @param obj_dp pointer to animage object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
*/
bool lv_img_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
{
bool valid = true;
/* Include the ancient signal function */
valid = lv_obj_signal(obj_dp, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
lv_img_ext_t * img_p = lv_obj_get_ext(obj_dp);
switch(sign) {
case LV_SIGNAL_CLEANUP:
dm_free(img_p->fn_dp);
break;
default:
break;
}
}
return valid;
}
/**
* Return with a pointer to built-in style and/or copy it to a variable
* @param style a style name from lv_imgs_builtin_t enum
* @param copy_p copy the style to this variable. (NULL if unused)
* @return pointer to an lv_imgs_t style
*/
lv_imgs_t * lv_imgs_get(lv_imgs_builtin_t style, lv_imgs_t * copy_p)
{
lv_imgs_t * style_p;
switch(style) {
case LV_IMGS_DEF:
style_p = &lv_imgs_def;
break;
case LV_IMGS_TRANSP:
style_p = &lv_imgs_transp;
break;
default:
style_p = NULL;
}
if(copy_p != NULL) {
if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_imgs_t));
else memcpy(copy_p, &lv_imgs_def, sizeof(lv_imgs_t));
}
return style_p;
}
/**
* Create a file to the RAMFS from a picture data
* @param fn file name of the new file (e.g. "pic1", will be avaliable at "U:/pic1")
* @param data_p pointer to a color map with lv_img_raw_header_t header
* @return result of the file operation. FS_RES_OK or any error from fs_res_t
*/
fs_res_t lv_img_create_file(const char * fn, const color_int_t * data_p)
{
const lv_img_raw_header_t * raw_p = (lv_img_raw_header_t *) data_p;
fs_res_t res;
res = ufs_create_const(fn, data_p, raw_p->w * raw_p->h * sizeof(color_t));
return res;
}
/*=====================
* Setter functions
*====================*/
/**
* Set a file to the image
* @param obj_dp pointer to an image object
* @param fn file name in the RAMFS to set as picture (e.g. "U:/pic1").
*/
void lv_img_set_file(lv_obj_t* obj_dp, const char * fn)
{
lv_img_ext_t * img_ext_p = lv_obj_get_ext(obj_dp);
fs_file_t file;
fs_res_t res;
lv_img_raw_header_t header;
uint32_t rn;
res = fs_open(&file, fn, FS_MODE_RD);
if(res == FS_RES_OK) {
res = fs_read(&file, &header, sizeof(header), &rn);
}
if(res != FS_RES_OK || rn != sizeof(header)) {
/*Create a dummy header*/
header.w = lv_obj_get_width(obj_dp);
header.h = lv_obj_get_height(obj_dp);
}
fs_close(&file);
img_ext_p->w = header.w;
img_ext_p->h = header.h;
#if LV_UPSCALE_MAP != 0
img_ext_p->w *= LV_DOWNSCALE;
img_ext_p->h *= LV_DOWNSCALE;
#endif
if(fn != NULL) {
img_ext_p->fn_dp = dm_realloc(img_ext_p->fn_dp, strlen(fn) + 1);
strcpy(img_ext_p->fn_dp, fn);
} else {
img_ext_p->fn_dp = NULL;
}
if(lv_img_get_auto_size(obj_dp) != false) {
lv_obj_set_size(obj_dp, img_ext_p->w, img_ext_p->h);
}
}
/**
* Enable the auto size feature. If enabled the object size will be same as the picture size.
* @param obj_dp pointer to an image
* @param en true: auto size enable, false: auto size disable
*/
void lv_img_set_auto_size(lv_obj_t* obj_dp, bool en)
{
lv_img_ext_t * img_ext_p = lv_obj_get_ext(obj_dp);
img_ext_p->auto_size = (en == false ? 0 : 1);
}
/*=====================
* Getter functions
*====================*/
/**
* Get the auto size enable attribute
* @param obj_dp pinter to an image
* @return true: auto size is enabled, false: auto size is disabled
*/
bool lv_img_get_auto_size(lv_obj_t* obj_dp)
{
lv_img_ext_t * img_ext_p = lv_obj_get_ext(obj_dp);
return img_ext_p->auto_size == 0 ? false : true;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the images
* @param obj_dp pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* @param return true/false, depends on 'mode'
*/
static bool lv_img_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode)
{
if(mode == LV_DESIGN_COVER_CHK) {
lv_imgs_t * imgs_p = lv_obj_get_style(obj_dp);
if(imgs_p->transp_en == 0) {
bool cover;
cover = area_is_in(mask_p, &obj_dp->cords);
return cover;
}
else return false;
}
lv_img_ext_t * img_ext_p = lv_obj_get_ext(obj_dp);
area_t cords;
lv_obj_get_cords(obj_dp, &cords);
opa_t opa = lv_obj_get_opa(obj_dp);
area_t cords_tmp;
cords_tmp.y1 = cords.y1;
cords_tmp.y2 = cords.y1 + img_ext_p->h - 1;
for(; cords_tmp.y1 < cords.y2; cords_tmp.y1 += img_ext_p->h, cords_tmp.y2 += img_ext_p->h) {
cords_tmp.x1 = cords.x1;
cords_tmp.x2 = cords.x1 + img_ext_p->w - 1;
for(; cords_tmp.x1 < cords.x2; cords_tmp.x1 += img_ext_p->w, cords_tmp.x2 += img_ext_p->w) {
lv_draw_img(&cords_tmp, mask_p, lv_obj_get_style(obj_dp),opa, img_ext_p->fn_dp, NULL);
}
}
return true;
}
#endif
/**
* @file lv_img.h
*
*/
#ifndef LV_IMG_H
#define LV_IMG_H
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if USE_LV_IMG != 0
#include "../lv_obj/lv_obj.h"
#include "misc/fs/fsint.h"
/*********************
* DEFINES
*********************/
#define LV_IMG_DECLARE(var_name) extern const color_int_t var_name[];
/**********************
* TYPEDEFS
**********************/
typedef struct
{
uint8_t transp_en :1;
}lv_imgs_t;
typedef struct
{
char* fn_dp;
cord_t w;
cord_t h;
uint8_t auto_size :1;
}lv_img_ext_t;
typedef enum
{
LV_IMGS_DEF,
LV_IMGS_TRANSP
}lv_imgs_builtin_t;
typedef struct
{
uint16_t w;
uint16_t h;
uint16_t res1;
uint16_t res2;
}lv_img_raw_header_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*Create function*/
lv_obj_t* lv_img_create(lv_obj_t* par_dp, lv_obj_t * copy_dp);
bool lv_img_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param);
void lv_img_set_file(lv_obj_t* obj_p, const char * fn);
fs_res_t lv_img_create_file(const char * fn, const color_int_t * data_p);
void lv_img_set_auto_size(lv_obj_t* obj_dp, bool mosaic_en);
bool lv_img_get_auto_size(lv_obj_t* obj_dp);
lv_imgs_t * lv_imgs_get(lv_imgs_builtin_t style, lv_imgs_t * copy_p);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file lv_rect.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if USE_LV_LABEL != 0
#include "misc/others/color.h"
#include "lv_label.h"
#include "../lv_obj/lv_obj.h"
#include "../lv_misc/text.h"
#include "../lv_draw/lv_draw.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool lv_label_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
/**********************
* STATIC VARIABLES
**********************/
static lv_labels_t lv_labels_def = {
.font = LV_FONT_DEFAULT, .color = COLOR_MAKE(0x10, 0x18, 0x20),
.letter_space = 3 * LV_STYLE_MULT, .line_space = 3 * LV_STYLE_MULT,
.mid = 1, .auto_break = 0
};
static lv_labels_t lv_labels_btn = {
.font = LV_FONT_DEFAULT, .color = COLOR_MAKE(0xd0, 0xe0, 0xf0),
.letter_space = 2 * LV_STYLE_MULT, .line_space = 2 * LV_STYLE_MULT,
.mid = 1, .auto_break = 0
};
static lv_labels_t lv_labels_title = {
.font = LV_FONT_DEFAULT, .color = COLOR_MAKE(0x10, 0x20, 0x30),
.letter_space = 4 * LV_STYLE_MULT, .line_space = 4 * LV_STYLE_MULT,
.mid = 0, .auto_break = 1
};
static lv_labels_t lv_labels_txt = {
.font = LV_FONT_DEFAULT, .color = COLOR_MAKE(0x16, 0x23, 0x34),
.letter_space = 1 * LV_STYLE_MULT, .line_space = 2 * LV_STYLE_MULT,
.mid = 0, .auto_break = 1
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Create a label objects
* @param par_dp pointer to an object, it will be the parent of the new label
* @param copy_dp pointer to a button object, if not NULL then the new object will be copied from it
* @return pointer to the created button
*/
lv_obj_t* lv_label_create(lv_obj_t* par_dp, lv_obj_t * ori_dp)
{
/*Create a basic object*/
lv_obj_t* new_obj = lv_obj_create(par_dp, ori_dp);
dm_assert(new_obj);
/*Extend the basic object to a label object*/
lv_obj_alloc_ext(new_obj, sizeof(lv_label_ext_t));
lv_label_ext_t * label_p = lv_obj_get_ext(new_obj);
label_p->txt = NULL;
lv_obj_set_design_f(new_obj, lv_label_design);
lv_obj_set_signal_f(new_obj, lv_label_signal);
/*Init the new label*/
if(ori_dp == NULL) {
lv_obj_set_opa(new_obj, OPA_COVER);
lv_obj_set_click(new_obj, false);
lv_obj_set_style(new_obj, &lv_labels_def);
lv_label_set_text(new_obj, "Text");
}
/*Copy 'ori_dp' if not NULL*/
else {
lv_obj_set_opa(new_obj, lv_obj_get_opa(ori_dp));
lv_obj_set_click(new_obj, lv_obj_get_click(ori_dp));
lv_obj_set_style(new_obj, lv_obj_get_style(ori_dp));
lv_label_set_text(new_obj, lv_label_get_text(ori_dp));
}
return new_obj;
}
/**
* Signal function of the label
* @param obj_dp pointer to a label object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
*/
bool lv_label_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
{
bool valid;
/* Include the ancient signal function */
valid = lv_obj_signal(obj_dp, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
lv_label_ext_t * label_p = lv_obj_get_ext(obj_dp);
/*No signal handling*/
switch(sign) {
case LV_SIGNAL_CLEANUP:
dm_free(label_p->txt);
label_p->txt = NULL;
break;
case LV_SIGNAL_STYLE_CHG:
lv_label_set_text(obj_dp, lv_label_get_text(obj_dp));
break;
default:
break;
}
}
return valid;
}
/*=====================
* Setter functions
*====================*/
/**
* Set a new text for a label
* @param obj_dp pointer to a label object
* @param text '\0' terminated chacter string
*/
void lv_label_set_text(lv_obj_t * obj_dp, const char * text)
{
if(text == NULL) return;
lv_obj_inv(obj_dp);
lv_label_ext_t * label_p = lv_obj_get_ext(obj_dp);
uint32_t len = strlen(text) + 1;
if(label_p->txt != NULL && text != label_p->txt) {
dm_free(label_p->txt);
}
label_p->txt = dm_alloc(len);
strcpy(label_p->txt, text);
uint32_t line_start = 0;
uint32_t new_line_start = 0;
cord_t max_length = lv_obj_get_width(obj_dp);
lv_labels_t * labels_p = lv_obj_get_style(obj_dp);
const font_t * font_p = font_get(labels_p->font);
uint8_t letter_height = font_get_height(font_p);
cord_t new_height = 0;
cord_t longest_line = 0;
cord_t act_line_length;
/*If the auto-break is not enabled the set the max length to very big */
if(labels_p->auto_break == 0) {
max_length = LV_CORD_MAX;
}
/*Calc. the height and longest line*/;
while (text[line_start] != '\0')
{
new_line_start += txt_get_next_line(&text[line_start], font_p, labels_p->letter_space, max_length);
new_height += letter_height;
new_height += labels_p->line_space;
/*If no auto break then calc. the longest line */
if(labels_p->auto_break == false) {
act_line_length = txt_get_length(&text[line_start], new_line_start - line_start,
font_p, labels_p->letter_space);
if(act_line_length > longest_line) {
longest_line = act_line_length;
}
}
line_start = new_line_start;
}
/*Correction with the last line space*/
new_height -= labels_p->line_space;
lv_obj_set_height(obj_dp, new_height);
/*Refresh the length if no autobreak*/
if(labels_p->auto_break == 0) {
lv_obj_set_width(obj_dp, longest_line);
}
lv_obj_inv(obj_dp);
}
/*=====================
* Getter functions
*====================*/
/**
* Get the text of a label
* @param obj_dp pointer to a label object
* @return the text of the label
*/
const char * lv_label_get_text(lv_obj_t* obj_dp)
{
lv_label_ext_t * label_p = lv_obj_get_ext(obj_dp);
return label_p->txt;
}
/**
* Return with a pointer to a built-in style and/or copy it to a variable
* @param style a style name from lv_labels_builtin_t enum
* @param copy_p copy the style to this variable. (NULL if unused)
* @return pointer to an lv_labels_t style
*/
lv_labels_t * lv_labels_get(lv_labels_builtin_t style, lv_labels_t * copy_p)
{
lv_labels_t * style_p;
switch(style) {
case LV_LABELS_DEF:
style_p = &lv_labels_def;
break;
case LV_LABELS_BTN:
style_p = &lv_labels_btn;
break;
case LV_LABELS_TXT:
style_p = &lv_labels_txt;
break;
case LV_LABELS_TITLE:
style_p = &lv_labels_title;
break;
default:
style_p = NULL;
}
if(copy_p != NULL) {
if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_labels_t));
else memcpy(copy_p, &lv_labels_def, sizeof(lv_labels_t));
}
return style_p;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the labels
* @param obj_dp pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* @param return true/false, depends on 'mode'
*/
static bool lv_label_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode)
{
/* A label never covers an area */
if(mode == LV_DESIGN_COVER_CHK) return false;
/*TEST: draw a background for the label*/
/*lv_vfill(&obj_dp->cords, mask_p, COLOR_LIME, OPA_COVER);*/
area_t cords;
lv_obj_get_cords(obj_dp, &cords);
opa_t opa= lv_obj_get_opa(obj_dp);
const char * txt = lv_label_get_text(obj_dp);
lv_draw_label(&cords, mask_p, lv_obj_get_style(obj_dp), opa, txt);
return true;
}
#endif
/**
* @file lv_rect.h
*
*/
#ifndef LV_LABEL_H
#define LV_LABEL_H
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if USE_LV_LABEL != 0
#include "../lv_obj/lv_obj.h"
#include "../lv_misc/font.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct
{
font_types_t font;
color_t color;
color_t bg_color;
uint16_t letter_space;
uint16_t line_space;
uint8_t mid :1;
uint8_t auto_break :1;
}lv_labels_t;
typedef struct
{
char* txt;
}lv_label_ext_t;
typedef enum
{
LV_LABELS_DEF,
LV_LABELS_BTN,
LV_LABELS_TXT,
LV_LABELS_TITLE,
}lv_labels_builtin_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*Create function*/
lv_obj_t* lv_label_create(lv_obj_t* par_dp, lv_obj_t * ori_dp);
bool lv_label_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param);
lv_labels_t * lv_labels_get(lv_labels_builtin_t style, lv_labels_t * copy_p);
void lv_label_set_text(lv_obj_t* obj_dp, const char * text);
const char * lv_label_get_text(lv_obj_t* obj_dp);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file lv_line.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#if USE_LV_LINE != 0
#include "lv_line.h"
#include "../lv_draw/lv_draw_vbasic.h"
#include "../lv_draw/lv_draw_rbasic.h"
#include "../lv_draw/lv_draw.h"
#include <lvgl/lv_misc/2d.h>
#include <misc/math/math_base.h>
#include <misc/mem/dyn_mem.h>
#include <misc/others/color.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool lv_line_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
/**********************
* STATIC VARIABLES
**********************/
static lv_lines_t lv_lines_def = { .width = 2 * LV_STYLE_MULT, .color = COLOR_RED,
.bg_color = COLOR_BLACK, .bg_opa = 0};
static lv_lines_t lv_lines_decor = { .width = 1 * LV_STYLE_MULT, .color = COLOR_GRAY,
.bg_color = COLOR_BLACK, .bg_opa = 0};
static lv_lines_t lv_lines_chart = { .width = 3 * LV_STYLE_MULT, .color = COLOR_BLUE,
.bg_color = COLOR_BLACK, .bg_opa = 0};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Create a line objects
* @param par_dp pointer to an object, it will be the parent of the new line
* @return pointer to the created line
*/
lv_obj_t* lv_line_create(lv_obj_t* par_dp, lv_obj_t * copy_dp)
{
/*Create a basic object*/
lv_obj_t* new_obj_dp = lv_obj_create(par_dp, copy_dp);
dm_assert(new_obj_dp);
/*Extend the basic object to rectangle object*/
lv_line_t *line_ext_p = lv_obj_alloc_ext(new_obj_dp, sizeof(lv_line_t));
lv_obj_set_design_f(new_obj_dp, lv_line_design);
lv_obj_set_signal_f(new_obj_dp, lv_line_signal);
/*Init the new rectangle*/
if(copy_dp == NULL) {
line_ext_p->point_num = 0;
line_ext_p->point_p = NULL;
line_ext_p->auto_size = 1;
line_ext_p->y_inv = 0;
lv_obj_set_style(new_obj_dp, &lv_lines_def);
}
/*Copy 'copy_p' is not NULL*/
else {
lv_line_set_auto_size(new_obj_dp,lv_line_get_auto_size(copy_dp));
lv_line_set_y_inv(new_obj_dp,lv_line_get_y_inv(copy_dp));
lv_line_set_auto_size(new_obj_dp,lv_line_get_auto_size(copy_dp));
lv_line_set_points(new_obj_dp, LV_EA(copy_dp, lv_line_t)->point_p,
LV_EA(copy_dp, lv_line_t)->point_num);
}
return new_obj_dp;
}
/**
* Signal function of the line
* @param obj_dp pointer to a line object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
*/
bool lv_line_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
{
bool valid;
/* Include the ancient signal function */
valid = lv_obj_signal(obj_dp, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
switch(sign) {
default:
break;
}
}
return valid;
}
/*=====================
* Setter functions
*====================*/
/**
* Set an array of points. The line object will connect these points.
* @param obj_dp pointer to a line object
* @param point_a an array of points. Only the address is saved,
* so the array can be a local variable which will be destroyed
* @param point_num number of points in 'point_a'
*/
void lv_line_set_points(lv_obj_t* obj_dp, const point_t * point_a, uint16_t point_num)
{
lv_line_t * line_p = lv_obj_get_ext(obj_dp);
line_p->point_p = point_a;
line_p->point_num = point_num;
if(point_num > 0 && line_p->auto_size != 0) {
uint16_t i;
cord_t xmax = LV_CORD_MIN;
cord_t ymax = LV_CORD_MIN;
for(i = 0; i < point_num; i++) {
xmax = max(point_a[i].x, xmax);
ymax = max(point_a[i].y, ymax);
}
lv_lines_t * lines_p = lv_obj_get_style(obj_dp);
lv_obj_set_size(obj_dp, xmax + lines_p->width, ymax + lines_p->width);
}
}
/**
* Enable (or disable) the auto-size option. The size of the object will fit to its points.
* (set width to x max and height to y max)
* @param obj_dp pointer to a line object
* @param en true: auto size is enabled, false: auto size is disabled
*/
void lv_line_set_auto_size(lv_obj_t * obj_dp, bool en)
{
lv_line_t * line_p = lv_obj_get_ext(obj_dp);
line_p->auto_size = en == false ? 0 : 1;
/*Refresh the object*/
if(en != false) {
lv_line_set_points(obj_dp, line_p->point_p, line_p->point_num);
}
}
/**
* Enable (or disable) the y coordinate inversion.
* If enabled then y will be subtracted from the height of the object,
* therefore the y=0 coordinate will be on the bottom.
* @param obj_dp pointer to a line object
* @param en true: enable the y inversion, false:disable the y inversion
*/
void lv_line_set_y_inv(lv_obj_t * obj_dp, bool en)
{
lv_line_t * line_p = lv_obj_get_ext(obj_dp);
line_p->y_inv = en == false ? 0 : 1;
lv_obj_inv(obj_dp);
}
/*=====================
* Getter functions
*====================*/
/**
* Get the auto size attribute
* @param obj_dp pointer to a line object
* @return true: auto size is enabled, false: disabled
*/
bool lv_line_get_auto_size(lv_obj_t * obj_dp)
{
lv_line_t * line_p = lv_obj_get_ext(obj_dp);
return line_p->auto_size == 0 ? false : true;
}
/**
* Get the y inversion attribute
* @param obj_dp pointer to a line object
* @return true: y inversion is enabled, false: disabled
*/
bool lv_line_get_y_inv(lv_obj_t * obj_dp)
{
lv_line_t * line_p = lv_obj_get_ext(obj_dp);
return line_p->y_inv == 0 ? false : true;
}
/**
* Return with a pointer to a built-in style and/or copy it to a variable
* @param style a style name from lv_lines_builtin_t enum
* @param copy_p copy the style to this variable. (NULL if unused)
* @return pointer to an lv_lines_t style
*/
lv_lines_t * lv_lines_get(lv_lines_builtin_t style, lv_lines_t * copy_p)
{
lv_lines_t *style_p;
switch(style) {
case LV_LINES_DEF:
style_p = &lv_lines_def;
break;
case LV_LINES_DECOR:
style_p = &lv_lines_decor;
break;
case LV_LINES_CHART:
style_p = &lv_lines_chart;
break;
default:
style_p = NULL;
}
if(copy_p != NULL) {
if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_lines_t));
else memcpy(copy_p, &lv_lines_def, sizeof(lv_lines_t));
}
return style_p;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the lines
* @param obj_dp pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* @param return true/false, depends on 'mode'
*/
static bool lv_line_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode)
{
/*A line never covers an area*/
if(mode == LV_DESIGN_COVER_CHK) return false;
lv_line_t * line_p = lv_obj_get_ext(obj_dp);
if(line_p->point_num == 0 || line_p->point_p == NULL) return false;
lv_lines_t * lines_p = lv_obj_get_style(obj_dp);
if(lines_p->bg_opa != 0) {
#if LV_VDB_SIZE != 0
lv_vfill(&obj_dp->cords, mask_p, lines_p->bg_color, lines_p->bg_opa * 255 / 100);
#else
lv_rfill(&obj_dp->cords, mask_p, lines_p->bg_color, lines_p->bg_opa * 255 / 100);
#endif
}
opa_t opa = lv_obj_get_opa(obj_dp);
area_t area;
lv_obj_get_cords(obj_dp, &area);
cord_t x_ofs = area.x1;
cord_t y_ofs = area.y1;
point_t p1;
point_t p2;
cord_t h = lv_obj_get_height(obj_dp);
uint16_t i;
/*Read all pints and draw the lines*/
for (i = 0; i < line_p->point_num - 1; i++) {
p1.x = line_p->point_p[i].x + x_ofs;
p2.x = line_p->point_p[i + 1].x + x_ofs;
if(line_p->y_inv == 0) {
p1.y = line_p->point_p[i].y + y_ofs;
p2.y = line_p->point_p[i + 1].y + y_ofs;
} else {
p1.y = h - line_p->point_p[i].y + y_ofs;
p2.y = h - line_p->point_p[i + 1].y + y_ofs;
}
lv_draw_line(&p1, &p2, mask_p, lines_p, opa);
}
return true;
}
#endif
/**
* @file lv_line.h
*
*/
#ifndef LV_LINE_H
#define LV_LINE_H
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#if USE_LV_LINE != 0
#include "lvgl/lv_obj/lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct
{
const point_t * point_p;
uint16_t point_num;
uint8_t auto_size :1;
uint8_t y_inv :1;
}lv_line_t;
typedef struct
{
color_t color;
color_t bg_color;
uint16_t width;
opa_t bg_opa;
}lv_lines_t;
typedef enum
{
LV_LINES_DEF,
LV_LINES_DECOR,
LV_LINES_CHART,
}lv_lines_builtin_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t* lv_line_create(lv_obj_t * par_dp, lv_obj_t * copy_dp);
bool lv_line_signal(lv_obj_t * obj_dp, lv_signal_t sign, void * param);
lv_lines_t * lv_lines_get(lv_lines_builtin_t style, lv_lines_t * copy_p);
void lv_line_set_points(lv_obj_t * obj_dp, const point_t * point_a, uint16_t point_num);
void lv_line_set_auto_size(lv_obj_t * obj_dp, bool en);
void lv_line_set_y_inv(lv_obj_t * obj_dp, bool en);
bool lv_line_get_auto_size(lv_obj_t * obj_dp);
bool lv_line_get_y_inv(lv_obj_t * obj_dp);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file lv_temp.c
*
*/
/*Search an replace: templ -> object short name (e.g. btn, label etc)
* TEMPLATE -> object normal name (e.g. button, label etc.)
*Modify USE_LV_TEMPL by hand */
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#if USE_LV_TEMPL != 0
#include "lv_templ.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool lv_templ_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
/**********************
* STATIC VARIABLES
**********************/
static lv_templs_t lv_templs_def =
{ /*Create a default style*/ };
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/*-----------------
* Create function
*-----------------*/
/**
* Create a TEMPLATE objects
* @param par_dp pointer to an object, it will be the parent of the new label
* @return pointer to the created label
*/
lv_obj_t* lv_templ_create(lv_obj_t* par_dp)
{
/*Create a basic object*/
lv_obj_t* new_obj = lv_obj_create(par_dp);
dm_assert(new_obj);
/*Init the new TEMPLATE object*/
return new_obj;
}
/**
* Signal function of the TEMPLATE
* @param obj_dp pointer to a TEMPLATE object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
*/
bool lv_rect_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
{
bool valid;
/* Include the ancient signal function */
valid = lv_obj_signal(obj_dp, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
switch(sign) {
default:
break;
}
}
return valid;
}
/**
* Return with a pointer to a built-in style and/or copy it to a variable
* @param style a style name from lv_rects_builtin_t enum
* @param copy_p copy the style to this variable. (NULL if unused)
* @return pointer to an lv_templs_t style
*/
lv_templs_t * lv_rects_get(lv_templs_builtin_t style, lv_templs_t * copy_p)
{
lv_rects_t *style_p;
switch(style) {
case LV_RECTS_DEF:
style_p = &lv_rects_def;
break;
case LV_RECTS_BORDER:
style_p = &lv_rects_border;
break;
case LV_RECTS_TRANSP:
style_p = &lv_rects_transp;
break;
default:
style_p = NULL;
}
if(copy_p != NULL) {
if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_templs_t));
else memcpy(copy_p, &lv_rects_def, sizeof(lv_templs_t));
}
return style_p;
}
/*=====================
* Setter functions
*====================*/
/*=====================
* Getter functions
*====================*/
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the TEMPLATEs
* @param obj_dp pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* @param return true/false, depends on 'mode'
*/
static bool lv_rect_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode)
{
if(mode == LV_DESIGN_COVER_CHK) {
/*Return false if the object is not covers the mask_p area*/
return false;
}
/*Draw the object*/
return true;
}
#endif
/**
* @file lv_rect.h
*
*/
#ifndef LV_RECT_H
#define LV_RECT_H
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#if USE_LV_TEMPL != 0
#include "../lv_obj/lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/*Style of TEMPLATE*/
typedef struct
{
}lv_templs_t;
/*Built-in styles of TEMPLATE*/
typedef enum
{
LV_RECTS_DEF,
LV_RECTS_TRANSP,
LV_RECTS_BORDER,
}lv_templs_builtin_t;
/*Data of TEMPLATE*/
typedef struct
{
}lv_templ_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_obj_t* lv_templ_create(lv_obj_t* par_dp);
bool lv_templ_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param);
lv_templs_t * lv_templs_get(lv_templs_builtin_t style, lv_templs_t * copy_p);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file lv_page.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if USE_LV_PAGE != 0
#include "../../misc/math/math_base.h"
#include "../lv_objx/lv_page.h"
#include "../lv_objx/lv_rect.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_page_sb_refresh(lv_obj_t* main_dp);
/**********************
* STATIC VARIABLES
**********************/
static lv_pages_t lv_pages_def =
{
.bg_rects.mcolor = COLOR_WHITE,
.bg_rects.gcolor = COLOR_SILVER,
.bg_rects.bcolor = COLOR_GRAY,
.bg_rects.bopa = 50,
.bg_rects.bwidth = 0 * LV_STYLE_MULT,
.bg_rects.round = 2 * LV_STYLE_MULT,
.bg_rects.empty = 0,
.sb_rects.mcolor = COLOR_BLACK,
.sb_rects.gcolor = COLOR_BLACK,
.sb_rects.bcolor = COLOR_WHITE,
.sb_rects.bopa = 50,
.sb_rects.bwidth = 1 * LV_STYLE_MULT,
.sb_rects.round = 5 * LV_STYLE_MULT,
.sb_rects.empty = 0,
.sb_width= 8 * LV_STYLE_MULT,
.sb_opa=50,
.sb_mode = LV_PAGE_SB_MODE_ON,
.margin_hor = 10 * LV_STYLE_MULT,
.margin_ver = 10 * LV_STYLE_MULT,
.padding_hor = 10 * LV_STYLE_MULT,
.padding_ver = 10 * LV_STYLE_MULT,
};
static lv_pages_t lv_pages_paper =
{
.bg_rects.mcolor = COLOR_WHITE,
.bg_rects.gcolor = COLOR_WHITE,
.bg_rects.bcolor = COLOR_GRAY,
.bg_rects.bopa = 100,
.bg_rects.bwidth = 2 * LV_STYLE_MULT,
.bg_rects.round = 0 * LV_STYLE_MULT,
.bg_rects.empty = 0,
.sb_rects.mcolor = COLOR_BLACK,
.sb_rects.gcolor = COLOR_BLACK,
.sb_rects.bcolor = COLOR_SILVER,
.sb_rects.bopa = 100,
.sb_rects.bwidth = 1 * LV_STYLE_MULT,
.sb_rects.round = 5 * LV_STYLE_MULT,
.sb_rects.empty = 0,
.sb_width = 10 * LV_STYLE_MULT,
.sb_opa=50,
.sb_mode = LV_PAGE_SB_MODE_ON,
.margin_hor = 15 * LV_STYLE_MULT,
.margin_ver = 15 * LV_STYLE_MULT,
.padding_hor = 10 * LV_STYLE_MULT,
.padding_ver = 10 * LV_STYLE_MULT,
};
static lv_pages_t lv_pages_transp =
{
.bg_rects.empty = 1,
.sb_rects.mcolor = COLOR_BLACK,
.sb_rects.gcolor = COLOR_BLACK,
.sb_rects.bcolor = COLOR_WHITE,
.sb_rects.bopa = 0,
.sb_rects.bwidth = 1 * LV_STYLE_MULT,
.sb_rects.round = 5 * LV_STYLE_MULT,
.sb_rects.empty = 0,
.sb_width = 8 * LV_STYLE_MULT,
.sb_opa = 50,
.sb_mode = LV_PAGE_SB_MODE_AUTO,
.margin_hor = 0 * LV_STYLE_MULT,
.margin_ver = 0 * LV_STYLE_MULT,
};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/*-----------------
* Create function
*-----------------*/
/**
* Create a page objects
* @param par_dp pointer to an object, it will be the parent of the new page
* @return pointer to the created page
*/
lv_obj_t* lv_page_create(lv_obj_t * par_dp, lv_obj_t * ori_dp)
{
lv_obj_t* new_dp = NULL;
/*Create a basic object. Page elements will be stored here*/
new_dp = lv_rect_create(par_dp, ori_dp);
/*Init the new object*/
lv_page_t * page_p = lv_obj_alloc_ext(new_dp, sizeof(lv_page_t));
/*Init the main rectangle if it is not copied*/
if(ori_dp == NULL) {
lv_obj_set_size(new_dp, 100,200);
lv_obj_set_drag(new_dp, true);
lv_obj_set_drag_throw(new_dp, true);
lv_obj_set_style(new_dp, &lv_pages_def);
} else {
lv_obj_set_style(new_dp, lv_obj_get_style(ori_dp));
}
lv_pages_t * pages_p = lv_obj_get_style(new_dp);
/*Create horizontal scroll bar*/
page_p->sbh_dp = lv_rect_create(par_dp, NULL);
lv_obj_set_height(page_p->sbh_dp, pages_p->sb_width);
lv_obj_set_style(page_p->sbh_dp, &pages_p->sb_rects);
if(pages_p->sb_mode == LV_PAGE_SB_MODE_ON) {
lv_obj_set_opa(page_p->sbh_dp, (pages_p->sb_opa * OPA_COVER) / 100);
} else {
lv_obj_set_opa(page_p->sbh_dp, OPA_TRANSP);
}
/*Create vertical scroll bar*/
page_p->sbv_dp =lv_rect_create(par_dp, NULL);
lv_obj_set_width(page_p->sbv_dp, pages_p->sb_width);
lv_obj_set_style(page_p->sbv_dp, &pages_p->sb_rects);
if(lv_pages_def.sb_mode == LV_PAGE_SB_MODE_ON) {
lv_obj_set_opa(page_p->sbv_dp, (pages_p->sb_opa * OPA_COVER) / 100);
} else {
lv_obj_set_opa(page_p->sbv_dp, OPA_TRANSP);
}
lv_obj_set_signal_f(new_dp, lv_page_signal);
lv_page_sb_refresh(new_dp);
return new_dp;
}
/**
* Signal function of the page
* @param obj_dp pointer to a page object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
*/
bool lv_page_signal(lv_obj_t* obj_dp, lv_signal_t sign, void* param)
{
bool obj_valid = true;
/* Include the ancient signal function */
obj_valid = lv_rect_signal(obj_dp, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(obj_valid != false) {
cord_t new_x;
cord_t new_y;
bool refr_x = false;
bool refr_y = false;
area_t page_cords;
area_t par_cords;
lv_obj_t * i;
lv_obj_t * par_dp = lv_obj_get_parent(obj_dp);
lv_page_t * page_ext_p = lv_obj_get_ext(obj_dp);
lv_pages_t * pages_p = lv_obj_get_style(obj_dp);
switch(sign) {
case LV_SIGNAL_CORD_CHG:
new_x = lv_obj_get_x(obj_dp);
new_y = lv_obj_get_y(obj_dp);
lv_obj_get_cords(par_dp, &par_cords);
lv_obj_get_cords(obj_dp, &page_cords);
/*page width smaller then parent width? -> align to left*/
if(area_get_width(&page_cords) <= area_get_width(&par_cords) - pages_p->margin_hor * 2) {
if(page_cords.x1 - pages_p->margin_hor != par_cords.x1) {
new_x = pages_p->margin_hor;
refr_x = true;
}
} else {
if(page_cords.x2 + pages_p->margin_hor < par_cords.x2) {
new_x = area_get_width(&par_cords) - area_get_width(&page_cords) - pages_p->margin_hor; /* Right align */
refr_x = true;
}
if (page_cords.x1 - pages_p->margin_hor > par_cords.x1) {
new_x = pages_p->margin_hor; /*Left align*/
refr_x = true;
}
}
/*Wrong in y?*/
if(area_get_height(&page_cords) <= area_get_height(&par_cords) - pages_p->margin_ver * 2) {
if(page_cords.y1 - pages_p->margin_ver != par_cords.y1) {
new_y = pages_p->margin_ver;
refr_y = true;
}
} else {
if(page_cords.y2 + pages_p->margin_ver < par_cords.y2) {
new_y = area_get_height(&par_cords) - area_get_height(&page_cords) - pages_p->margin_ver; /* Bottom align */
refr_y = true;
}
if (page_cords.y1 - pages_p->margin_ver > par_cords.y1) {
new_y = pages_p->margin_ver; /*Top align*/
refr_y = true;
}
}
if(refr_x != false || refr_y != false) {
lv_obj_set_pos(obj_dp, new_x, new_y);
}
lv_page_sb_refresh(obj_dp);
break;
case LV_SIGNAL_DRAG_BEGIN:
if(pages_p->sb_mode == LV_PAGE_SB_MODE_AUTO ) {
if(lv_obj_get_height(page_ext_p->sbv_dp) < lv_obj_get_height(par_dp) - pages_p->sb_width) {
lv_obj_set_opa(page_ext_p->sbv_dp, (pages_p->sb_opa * OPA_COVER) / 100);
}
if(lv_obj_get_width(page_ext_p->sbh_dp) < lv_obj_get_width(par_dp) - pages_p->sb_width) {
lv_obj_set_opa(page_ext_p->sbh_dp, (pages_p->sb_opa * OPA_COVER) / 100);
}
}
break;
case LV_SIGNAL_DRAG_END:
if(pages_p->sb_mode == LV_PAGE_SB_MODE_AUTO) {
lv_obj_set_opa(page_ext_p->sbh_dp, OPA_TRANSP);
lv_obj_set_opa(page_ext_p->sbv_dp, OPA_TRANSP);
}
break;
case LV_SIGNAL_CHILD_CHG:
page_cords.x1 = LV_CORD_MAX;
page_cords.y1 = LV_CORD_MAX;
page_cords.x2 = LV_CORD_MIN;
page_cords.y2 = LV_CORD_MIN;
LL_READ(obj_dp->child_ll, i) {
page_cords.x1 = min(page_cords.x1, i->cords.x1);
page_cords.y1 = min(page_cords.y1, i->cords.y1);
page_cords.x2 = max(page_cords.x2, i->cords.x2);
page_cords.y2 = max(page_cords.y2, i->cords.y2);
}
/*If the value is not the init value then the page has >=1 child.*/
if(page_cords.x1 != LV_CORD_MAX) {
page_cords.x1 -= pages_p->padding_hor;
page_cords.x2 += pages_p->padding_hor;
page_cords.y1 -= pages_p->padding_ver;
page_cords.y2 += pages_p->padding_ver;
area_cpy(&obj_dp->cords, &page_cords);
lv_obj_set_pos(obj_dp, lv_obj_get_x(obj_dp),
lv_obj_get_y(obj_dp));
} else {
lv_obj_set_size(obj_dp, 10, 10);
}
lv_obj_inv(par_dp);
break;
case LV_SIGNAL_STYLE_CHG:
/* Set the styles only if they are different else infinite loop
* will be created from lv_obj_set_style*/
if(lv_obj_get_style(page_ext_p->sbh_dp) != &pages_p->sb_rects) {
lv_obj_set_style(page_ext_p->sbh_dp, &pages_p->sb_rects);
lv_obj_set_style(page_ext_p->sbv_dp, &pages_p->sb_rects);
lv_obj_set_style(obj_dp, &pages_p->bg_rects);
}
if(pages_p->sb_mode == LV_PAGE_SB_MODE_ON) {
lv_obj_set_opa(page_ext_p->sbv_dp, (pages_p->sb_opa * OPA_COVER) / 100);
lv_obj_set_opa(page_ext_p->sbh_dp, (pages_p->sb_opa * OPA_COVER) / 100);
} else {
lv_obj_set_opa(page_ext_p->sbv_dp, OPA_TRANSP);
lv_obj_set_opa(page_ext_p->sbh_dp, OPA_TRANSP);
}
lv_page_sb_refresh(obj_dp);
break;
default:
break;
}
}
return obj_valid;
}
/**
* Glue the object to the page. After it the page can be moved (dragged) with this object too.
* @param obj_dp pointer to an object on a page
* @param en true: enable glue, false: disable glue
*/
void lv_page_glue_obj(lv_obj_t* obj_dp, bool en)
{
lv_obj_set_drag_parent(obj_dp, en);
lv_obj_set_drag(obj_dp, en);
}
/**
* Return with a pointer to a built-in style and/or copy it to a variable
* @param style a style name from lv_pages_builtin_t enum
* @param copy_p copy the style to this variable. (NULL if unused)
* @return pointer to an lv_pages_t style
*/
lv_pages_t * lv_pages_get(lv_pages_builtin_t style, lv_pages_t * to_copy)
{
lv_pages_t * style_p;
switch(style) {
case LV_PAGES_DEF:
style_p = &lv_pages_def;
break;
case LV_PAGES_PAPER:
style_p = &lv_pages_paper;
break;
case LV_PAGES_TRANSP:
style_p = &lv_pages_transp;
break;
default:
style_p = NULL;
}
if(to_copy != NULL) {
if(style_p != NULL) memcpy(to_copy, style_p, sizeof(lv_pages_t));
else memcpy(to_copy, &lv_pages_def, sizeof(lv_pages_t));
}
return style_p;
}
/*=====================
* Setter functions
*====================*/
/*=====================
* Getter functions
*====================*/
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the pages
* @param obj_dp pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* @param return true/false, depends on 'mode'
*/
static void lv_page_sb_refresh(lv_obj_t* page_dp)
{
lv_page_t * page_p = lv_obj_get_ext(page_dp);
lv_pages_t * pages_p = lv_obj_get_style(page_dp);
lv_obj_t* par_dp = lv_obj_get_parent(page_dp);
cord_t size_tmp;
cord_t page_w = lv_obj_get_width(page_dp) + 2 * pages_p->margin_hor;
cord_t page_h = lv_obj_get_height(page_dp) + 2 * pages_p->margin_ver;
cord_t par_w = lv_obj_get_width(par_dp);
cord_t par_h = lv_obj_get_height(par_dp);
/*Horizontal scrollbar*/
if(page_w <= par_w) { /*Full sized scroll bar*/
lv_obj_set_width(page_p->sbh_dp, par_w - pages_p->sb_width);
lv_obj_set_pos(page_p->sbh_dp, 0, par_h - pages_p->sb_width);
lv_obj_set_opa(page_p->sbh_dp, OPA_TRANSP);
} else {
if(pages_p->sb_mode == LV_PAGE_SB_MODE_ON) {
lv_obj_set_opa(page_p->sbh_dp, (pages_p->sb_opa * OPA_COVER) / 100);
}
size_tmp = ((par_w * (par_w - pages_p->sb_width)) / page_w);
lv_obj_set_width(page_p->sbh_dp, size_tmp);
lv_obj_set_pos(page_p->sbh_dp,
( -(lv_obj_get_x(page_dp) - pages_p->margin_hor) * (par_w - size_tmp - pages_p->sb_width)) /
(page_w - par_w),
par_h - pages_p->sb_width);
}
/*Vertical scrollbar*/
if(page_h <= par_h) { /*Full sized scroll bar*/
lv_obj_set_height(page_p->sbv_dp, par_h - pages_p->sb_width);
lv_obj_set_pos(page_p->sbv_dp, par_w - pages_p->sb_width, 0);
lv_obj_set_opa(page_p->sbv_dp, OPA_TRANSP);
} else {
if(pages_p->sb_mode == LV_PAGE_SB_MODE_ON) {
lv_obj_set_opa(page_p->sbv_dp, (pages_p->sb_opa * OPA_COVER) / 100);
}
size_tmp = ((par_h * (par_h - pages_p->sb_width)) / page_h);
lv_obj_set_height(page_p->sbv_dp, size_tmp);
lv_obj_set_pos(page_p->sbv_dp,
par_w - pages_p->sb_width,
(-(lv_obj_get_y(page_dp) - pages_p->margin_ver) * (par_h - size_tmp - pages_p->sb_width)) /
(page_h - par_h));
}
}
#endif
/**
* @file lv_page.h
*
*/
#ifndef LV_PAGE_H
#define LV_PAGE_H
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if USE_LV_PAGE != 0
#include "../lv_obj/lv_obj.h"
#include "lv_rect.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef enum
{
LV_PAGE_SB_MODE_OFF,
LV_PAGE_SB_MODE_ON,
LV_PAGE_SB_MODE_AUTO,
}lv_page_sb_mode_t;
typedef struct
{
lv_rects_t bg_rects;
lv_rects_t sb_rects;
cord_t sb_width;
cord_t margin_hor; /*Extra size between the parent and the page horizontally*/
cord_t margin_ver; /*Extra size between the parent and the page vertically*/
cord_t padding_hor; /*Extra size on page horizontally*/
cord_t padding_ver; /*Extra size on page vertically*/
lv_page_sb_mode_t sb_mode;
uint8_t sb_opa;
}lv_pages_t;
typedef struct
{
lv_obj_t* sbh_dp; /*Horizontal scrollbar*/
lv_obj_t* sbv_dp; /*Vertical scrollbar*/
}lv_page_t;
typedef enum
{
LV_PAGES_DEF,
LV_PAGES_PAPER,
LV_PAGES_TRANSP,
}lv_pages_builtin_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*Create function*/
lv_obj_t* lv_page_create(lv_obj_t* par_dp, lv_obj_t * ori_dp);
void lv_page_glue_obj(lv_obj_t* page_p, bool en);
lv_pages_t * lv_pages_get(lv_pages_builtin_t style, lv_pages_t * to_copy);
bool lv_page_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file lv_rect.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#if USE_LV_RECT != 0
#include "lv_rect.h"
#include "../lv_draw/lv_draw.h"
#include "../lv_draw/lv_draw_vbasic.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool lv_rect_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
/**********************
* STATIC VARIABLES
**********************/
static lv_rects_t lv_rects_def =
{ .mcolor = COLOR_MAKE(0x50, 0x70, 0x90), .gcolor = COLOR_MAKE(0x20, 0x40, 0x60),
.bcolor = COLOR_WHITE, .bwidth = 2 * LV_STYLE_MULT, .bopa = 50,
.round = 4 * LV_STYLE_MULT, .empty = 0 };
static lv_rects_t lv_rects_transp =
{ .bwidth = 0, .empty = 0 };
static lv_rects_t lv_rects_border =
{ .bcolor = COLOR_BLACK, .bwidth = 2 * LV_STYLE_MULT, .bopa = 100,
.round = 4 * LV_STYLE_MULT, .empty = 1 };
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/*-----------------
* Create function
*-----------------*/
/**
* Create a label objects
* @param par_dp pointer to an object, it will be the parent of the new label
* @param copy_dp pointer to a rectangle object, if not NULL then the new object will be copied from it
* @return pointer to the created label
*/
lv_obj_t* lv_rect_create(lv_obj_t* par_dp, lv_obj_t * copy_dp)
{
/*Create a basic object*/
lv_obj_t* new_obj_dp = lv_obj_create(par_dp, copy_dp);
dm_assert(new_obj_dp);
lv_obj_set_design_f(new_obj_dp, lv_rect_design);
lv_obj_set_signal_f(new_obj_dp, lv_rect_signal);
/*Init the new rectangle*/
if(copy_dp == NULL) {
lv_obj_set_style(new_obj_dp, &lv_rects_def);
}
/*Copy 'copy_dp' if it is not NULL*/
else {
lv_obj_set_style(new_obj_dp, lv_obj_get_style(copy_dp));
}
return new_obj_dp;
}
/**
* Signal function of the rectangle
* @param obj_dp pointer to a rectangle object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
*/
bool lv_rect_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
{
bool valid;
/* Include the ancient signal function */
valid = lv_obj_signal(obj_dp, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
switch(sign) {
default:
break;
}
}
return valid;
}
/**
* Return with a pointer to a built-in style and/or copy it to a variable
* @param style a style name from lv_rects_builtin_t enum
* @param copy_p copy the style to this variable. (NULL if unused)
* @return pointer to an lv_rects_t style
*/
lv_rects_t * lv_rects_get(lv_rects_builtin_t style, lv_rects_t * copy_p)
{
lv_rects_t *style_p;
switch(style) {
case LV_RECTS_DEF:
style_p = &lv_rects_def;
break;
case LV_RECTS_BORDER:
style_p = &lv_rects_border;
break;
case LV_RECTS_TRANSP:
style_p = &lv_rects_transp;
break;
default:
style_p = NULL;
}
if(copy_p != NULL) {
if(style_p != NULL) memcpy(copy_p, style_p, sizeof(lv_rects_t));
else memcpy(copy_p, &lv_rects_def, sizeof(lv_rects_t));
}
return style_p;
}
/*=====================
* Setter functions
*====================*/
/*=====================
* Getter functions
*====================*/
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the labels
* @param obj_dp pointer to an object
* @param mask the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW: draw the object (always return 'true')
* @param return true/false, depends on 'mode'
*/
static bool lv_rect_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode)
{
/* Because of the radius it is not sure the area is covered*/
if(mode == LV_DESIGN_COVER_CHK) {
if(LV_SA(obj_dp, lv_rects_t)->empty != 0) return false;
uint16_t r = LV_SA(obj_dp, lv_rects_t)->round;
area_t area_tmp;
/*Check horizontally without radius*/
lv_obj_get_cords(obj_dp, &area_tmp);
area_tmp.x1 += r;
area_tmp.x2 -= r;
if(area_is_in(mask_p, &area_tmp) == true) return true;
/*Check vertically without radius*/
lv_obj_get_cords(obj_dp, &area_tmp);
area_tmp.y1 += r;
area_tmp.y2 -= r;
if(area_is_in(mask_p, &area_tmp) == true) return true;
return false;
}
opa_t opa = lv_obj_get_opa(obj_dp);
area_t area;
lv_obj_get_cords(obj_dp, &area);
/*Draw the rectangle*/
lv_draw_rect(&area, mask_p, lv_obj_get_style(obj_dp), opa);
return true;
}
#endif
/**
* @file lv_rect.h
*
*/
#ifndef LV_RECT_H
#define LV_RECT_H
/*********************
* INCLUDES
*********************/
#include "../../lv_conf.h"
#if USE_LV_RECT != 0
#include "../lv_obj/lv_obj.h"
#include "../lv_obj/lv_dispi.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct
{
color_t mcolor;
color_t gcolor;
color_t bcolor;
uint16_t bwidth;
uint8_t bopa;
uint8_t empty :1;
uint16_t round;
}lv_rects_t;
typedef struct
{
}lv_rect_ext_t;
typedef enum
{
LV_RECTS_DEF,
LV_RECTS_TRANSP,
LV_RECTS_BORDER,
}lv_rects_builtin_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/*Create function*/
lv_obj_t* lv_rect_create(lv_obj_t* par_dp, lv_obj_t * copy_dp);
bool lv_rect_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param);
lv_rects_t * lv_rects_get(lv_rects_builtin_t style, lv_rects_t * copy_p);
/**********************
* MACROS
**********************/
#endif
#endif
/**
* @file lvgl.h
* Include all LittleV GL related headers
*/
#ifndef LV_GL_H
#define LV_GL_H
/*********************
* INCLUDES
*********************/
#include "lv_obj/lv_obj.h"
#include "lv_objx/lv_btn.h"
#include "lv_objx/lv_img.h"
#include "lv_objx/lv_label.h"
#include "lv_objx/lv_line.h"
#include "lv_objx/lv_page.h"
#include "lv_objx/lv_rect.h"
/*********************
* DEFINES
*********************/
#define LV_GL_VERSION_MAJOR 1
#define LV_GL_VERSION_MINOR 0
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment