acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_draw_sdl_line.c (5660B)

      1 /**
      2  * @file lv_draw_sdl_line.c
      3  *
      4  */
      5 
      6 /*********************
      7  *      INCLUDES
      8  *********************/
      9 #include "../../lv_conf_internal.h"
     10 
     11 #if LV_USE_GPU_SDL
     12 
     13 #include "lv_draw_sdl.h"
     14 #include "lv_draw_sdl_utils.h"
     15 #include "lv_draw_sdl_texture_cache.h"
     16 #include "lv_draw_sdl_composite.h"
     17 #include "lv_draw_sdl_mask.h"
     18 
     19 /*********************
     20  *      DEFINES
     21  *********************/
     22 #define ROUND_START 0x01
     23 #define ROUND_END 0x02
     24 /**********************
     25  *      TYPEDEFS
     26  **********************/
     27 
     28 typedef struct {
     29     lv_sdl_cache_key_magic_t magic;
     30     lv_coord_t length;
     31     lv_coord_t width;
     32     uint8_t round;
     33 } lv_draw_line_key_t;
     34 
     35 /**********************
     36  *  STATIC PROTOTYPES
     37  **********************/
     38 
     39 /**********************
     40  *  STATIC VARIABLES
     41  **********************/
     42 
     43 /**********************
     44  *      MACROS
     45  **********************/
     46 
     47 static lv_draw_line_key_t line_key_create(const lv_draw_line_dsc_t * dsc, lv_coord_t length);
     48 
     49 static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_draw_line_dsc_t * dsc,
     50                                          lv_coord_t length);
     51 
     52 /**********************
     53  *   GLOBAL FUNCTIONS
     54  **********************/
     55 void lv_draw_sdl_draw_line(lv_draw_ctx_t * draw_ctx, const lv_draw_line_dsc_t * dsc, const lv_point_t * point1,
     56                            const lv_point_t * point2)
     57 {
     58     lv_draw_sdl_ctx_t * sdl_ctx = (lv_draw_sdl_ctx_t *) draw_ctx;
     59     SDL_Renderer * renderer = sdl_ctx->renderer;
     60     lv_coord_t x1 = point1->x, x2 = point2->x, y1 = point1->y, y2 = point2->y;
     61     double length = SDL_sqrt(SDL_pow(x2 - x1, 2) + SDL_pow(y2 - y1, 2));
     62     if(length - (long) length > 0.5) {
     63         length = (long) length + 1;
     64     }
     65 
     66     double angle = SDL_atan2(y2 - y1, x2 - x1) * 180 / M_PI;
     67     lv_draw_line_key_t key = line_key_create(dsc, (lv_coord_t) length);
     68     SDL_Texture * texture = lv_draw_sdl_texture_cache_get(sdl_ctx, &key, sizeof(key), NULL);
     69     if(!texture) {
     70         texture = line_texture_create(sdl_ctx, dsc, (lv_coord_t) length);
     71         lv_draw_sdl_texture_cache_put(sdl_ctx, &key, sizeof(key), texture);
     72     }
     73 
     74     lv_area_t coords = {x1, y1, x2, y2};
     75     const lv_area_t * clip = draw_ctx->clip_area;
     76 
     77     SDL_Rect coords_r, clip_r;
     78     lv_area_to_sdl_rect(&coords, &coords_r);
     79     lv_area_to_sdl_rect(clip, &clip_r);
     80 
     81     lv_area_t t_coords = coords, t_clip = *clip, apply_area;
     82     lv_area_t extension = {dsc->width / 2, dsc->width / 2, dsc->width / 2, dsc->width / 2};
     83     lv_draw_sdl_composite_begin(sdl_ctx, &coords, clip, &extension, dsc->blend_mode, &t_coords, &t_clip,
     84                                 &apply_area);
     85 
     86     SDL_Color color;
     87     lv_color_to_sdl_color(&dsc->color, &color);
     88 
     89     SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
     90     SDL_SetTextureAlphaMod(texture, dsc->opa);
     91     SDL_Rect srcrect = {0, 0, (int) length + dsc->width + 2, dsc->width + 2},
     92              dstrect = {t_coords.x1 - 1 - dsc->width / 2, t_coords.y1 - 1, srcrect.w, srcrect.h};
     93     SDL_Point center = {1 + dsc->width / 2, 1 + dsc->width / 2};
     94 
     95     SDL_Rect clip_rect;
     96     lv_area_to_sdl_rect(&t_clip, &clip_rect);
     97     if(!SDL_RectEquals(&clip_rect, &dstrect) || angle != 0) {
     98         SDL_RenderSetClipRect(renderer, &clip_rect);
     99     }
    100     SDL_RenderCopyEx(renderer, texture, &srcrect, &dstrect, angle, &center, 0);
    101     SDL_RenderSetClipRect(renderer, NULL);
    102 
    103     lv_draw_sdl_composite_end(sdl_ctx, &apply_area, dsc->blend_mode);
    104 }
    105 
    106 /**********************
    107  *   STATIC FUNCTIONS
    108  **********************/
    109 
    110 static lv_draw_line_key_t line_key_create(const lv_draw_line_dsc_t * dsc, lv_coord_t length)
    111 {
    112     lv_draw_line_key_t key;
    113     lv_memset_00(&key, sizeof(lv_draw_line_key_t));
    114     key.magic = LV_GPU_CACHE_KEY_MAGIC_LINE;
    115     key.length = length;
    116     key.width = dsc->width;
    117     key.round = (dsc->round_start ? ROUND_START : 0) | (dsc->round_end ? ROUND_END : 0);
    118     return key;
    119 }
    120 
    121 static SDL_Texture * line_texture_create(lv_draw_sdl_ctx_t * sdl_ctx, const lv_draw_line_dsc_t * dsc, lv_coord_t length)
    122 {
    123     SDL_Texture * texture = SDL_CreateTexture(sdl_ctx->renderer, LV_DRAW_SDL_TEXTURE_FORMAT, SDL_TEXTUREACCESS_TARGET,
    124                                               length + dsc->width + 2, dsc->width + 2);
    125     SDL_Texture * target = SDL_GetRenderTarget(sdl_ctx->renderer);
    126     SDL_SetRenderTarget(sdl_ctx->renderer, texture);
    127     SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
    128     SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0x0);
    129     SDL_RenderClear(sdl_ctx->renderer);
    130     SDL_SetRenderDrawColor(sdl_ctx->renderer, 0xFF, 0xFF, 0xFF, 0xFF);
    131     SDL_Rect line_rect = {1 + dsc->width / 2, 1, length, dsc->width};
    132     SDL_RenderFillRect(sdl_ctx->renderer, &line_rect);
    133     if(dsc->round_start || dsc->round_end) {
    134         lv_draw_mask_radius_param_t param;
    135         lv_area_t round_area = {0, 0, dsc->width - 1, dsc->width - 1};
    136         lv_draw_mask_radius_init(&param, &round_area, LV_RADIUS_CIRCLE, false);
    137 
    138         int16_t mask_id = lv_draw_mask_add(&param, NULL);
    139         SDL_Texture * round_texture = lv_draw_sdl_mask_dump_texture(sdl_ctx->renderer, &round_area, &mask_id, 1);
    140         lv_draw_mask_remove_id(mask_id);
    141 
    142         SDL_Rect round_src = {0, 0, dsc->width, dsc->width};
    143         SDL_Rect round_dst = {line_rect.x - dsc->width / 2, 1, dsc->width, dsc->width};
    144         SDL_RenderCopy(sdl_ctx->renderer, round_texture, &round_src, &round_dst);
    145         round_dst.x = line_rect.w + dsc->width / 2;
    146         SDL_RenderCopy(sdl_ctx->renderer, round_texture, &round_src, &round_dst);
    147         SDL_DestroyTexture(round_texture);
    148     }
    149 
    150     SDL_SetRenderTarget(sdl_ctx->renderer, target);
    151     return texture;
    152 }
    153 
    154 #endif /*LV_USE_GPU_SDL*/