172 lines
4.1 KiB
C
172 lines
4.1 KiB
C
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <lvgl/lvgl.h>
|
|
|
|
struct tile_info
|
|
{
|
|
int len;
|
|
int items;
|
|
};
|
|
|
|
struct tile_map
|
|
{
|
|
uint8_t *data;
|
|
int w;
|
|
int h;
|
|
};
|
|
|
|
struct tile_layout
|
|
{
|
|
struct tile_map map;
|
|
lv_obj_t *layout;
|
|
int w;
|
|
int h;
|
|
int base_size;
|
|
int cols;
|
|
int rows;
|
|
int32_t *col_dsc;
|
|
int32_t *row_dsc;
|
|
};
|
|
|
|
#define MAP_DATA(m, x, y) (m->data[m->w * y + ((x & ~7) >> 3)])
|
|
#define DATA_MASK(x) ((1 << (x & 7)))
|
|
#define UNMARK_MAP(m, x, y) \
|
|
(MAP_DATA(m, x, y) &= ~DATA_MASK(x))
|
|
#define MARK_MAP(m, x, y) \
|
|
(MAP_DATA(m, x, y) |= DATA_MASK(x))
|
|
#define READ_MAP(m, x, y) \
|
|
(MAP_DATA(m, x, y) & DATA_MASK(x))
|
|
#define DEPART_AREA(a) int x, y, w, h;\
|
|
x = a->x1; \
|
|
y = a->y1; \
|
|
w = a->x2 - a->x1 + 1; \
|
|
h = a->y2 - a->y1 + 1;
|
|
|
|
static void unmark_area(struct tile_map *map, lv_area_t *area)
|
|
{
|
|
DEPART_AREA(area);
|
|
|
|
for (int i = 0; i < h; i++)
|
|
for (int j = 0; j < w; j++)
|
|
UNMARK_MAP(map, x + j, y + i);
|
|
}
|
|
|
|
static void mark_area(struct tile_map *map, lv_area_t *area)
|
|
{
|
|
DEPART_AREA(area);
|
|
|
|
for (int i = 0; i < h; i++)
|
|
for (int j = 0; j < w; j++)
|
|
MARK_MAP(map, x + j, y + i);
|
|
}
|
|
|
|
static int is_free_area(struct tile_map *map, lv_area_t *area)
|
|
{
|
|
struct tile_layout *tl = (struct tile_layout *)map;
|
|
DEPART_AREA(area);
|
|
|
|
for (int i = 0; i < h; i++)
|
|
{
|
|
for (int j = 0; j < w; j++)
|
|
{
|
|
if (((x + j) == tl->cols) || (y + i) == tl->rows)
|
|
return 0;
|
|
|
|
if (READ_MAP(map, x + j, y + i))
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void print_map(struct tile_map *map)
|
|
{
|
|
for (int i = 0; i < map->h; i++)
|
|
{
|
|
printf("[");
|
|
for (int j = 0; j < map->w * 8; j++)
|
|
printf(" %c", READ_MAP(map, j, i) ? 'X' : '_');
|
|
printf(" ]\n");
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
void *tile_layout_create(lv_obj_t *parent, int w, int h, int base_size)
|
|
{
|
|
struct tile_layout *tl;
|
|
|
|
tl = calloc(1, sizeof(struct tile_layout));
|
|
|
|
if (!w)
|
|
w = lv_obj_get_content_width(parent);
|
|
if (!h)
|
|
h = lv_obj_get_content_height(parent);
|
|
|
|
tl->cols = (float)w / base_size;
|
|
tl->rows = (float)h / base_size;
|
|
tl->w = tl->cols * base_size;
|
|
tl->h = tl->rows * base_size;
|
|
tl->map.w = ceil((float)tl->cols / 8.);
|
|
tl->map.h = tl->rows;
|
|
tl->map.data = calloc(tl->map.w * tl->map.h, sizeof(uint8_t));
|
|
tl->col_dsc = malloc((tl->cols + 1) * sizeof(int32_t));
|
|
tl->row_dsc = malloc((tl->rows + 1) * sizeof(int32_t));
|
|
|
|
for (int i = 0; i < tl->cols; i++)
|
|
tl->col_dsc[i] = base_size;
|
|
tl->col_dsc[tl->cols] = LV_GRID_TEMPLATE_LAST;
|
|
|
|
for (int i = 0; i < tl->rows; i++)
|
|
tl->row_dsc[i] = base_size;
|
|
tl->row_dsc[tl->rows] = LV_GRID_TEMPLATE_LAST;
|
|
|
|
tl->layout = lv_obj_create(parent);
|
|
lv_obj_remove_style_all(tl->layout);
|
|
lv_obj_set_size(tl->layout, tl->w, tl->h);
|
|
lv_obj_set_style_grid_column_dsc_array(tl->layout, tl->col_dsc, 0);
|
|
lv_obj_set_style_grid_row_dsc_array(tl->layout, tl->row_dsc, 0);
|
|
lv_obj_set_layout(tl->layout, LV_LAYOUT_GRID);
|
|
lv_obj_center(tl->layout);
|
|
|
|
return tl;
|
|
}
|
|
|
|
lv_obj_t *tile_layout_new_item(void *layout, int cols, int rows, int pad)
|
|
{
|
|
struct tile_layout *tl = layout;
|
|
lv_area_t area;
|
|
lv_obj_t *obj;
|
|
|
|
for (int i = 0; i < tl->rows; i++)
|
|
{
|
|
for (int j = 0; j < tl->cols; j++)
|
|
{
|
|
area.x1 = j;
|
|
area.y1 = i;
|
|
area.x2 = j + cols - 1;
|
|
area.y2 = i + rows - 1;
|
|
if (is_free_area(&tl->map, &area))
|
|
{
|
|
mark_area(&tl->map, &area);
|
|
if (pad)
|
|
return (void *)1;
|
|
|
|
obj = lv_obj_create(tl->layout);
|
|
lv_obj_remove_style_all(obj);
|
|
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, j, cols,
|
|
LV_GRID_ALIGN_STRETCH, i, rows);
|
|
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
|
|
|
|
return obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|