1 /**
2  * @file lv_draw_sw_letter.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "blend/lv_draw_sw_blend_private.h"
10 #include "../lv_draw_label_private.h"
11 #include "lv_draw_sw.h"
12 #if LV_USE_DRAW_SW
13 
14 #include "../../display/lv_display.h"
15 #include "../../misc/lv_math.h"
16 #include "../../misc/lv_assert.h"
17 #include "../../misc/lv_area.h"
18 #include "../../misc/lv_style.h"
19 #include "../../font/lv_font.h"
20 #include "../../core/lv_refr_private.h"
21 #include "../../stdlib/lv_string.h"
22 
23 /*********************
24  *      DEFINES
25  *********************/
26 
27 /**********************
28  *      TYPEDEFS
29  **********************/
30 
31 /**********************
32  *  STATIC PROTOTYPES
33  **********************/
34 
35 static void /* LV_ATTRIBUTE_FAST_MEM */ draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc,
36                                                        lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area);
37 
38 /**********************
39  *  STATIC VARIABLES
40  **********************/
41 
42 /**********************
43  *  GLOBAL VARIABLES
44  **********************/
45 
46 /**********************
47  *      MACROS
48  **********************/
49 
50 /**********************
51  *   GLOBAL FUNCTIONS
52  **********************/
53 
lv_draw_sw_letter(lv_draw_unit_t * draw_unit,const lv_draw_letter_dsc_t * dsc,const lv_area_t * coords)54 void lv_draw_sw_letter(lv_draw_unit_t * draw_unit, const lv_draw_letter_dsc_t * dsc, const lv_area_t * coords)
55 {
56     if(dsc->opa <= LV_OPA_MIN)
57         return;
58 
59     lv_draw_glyph_dsc_t glyph_dsc;
60     lv_draw_glyph_dsc_init(&glyph_dsc);
61     glyph_dsc.opa = dsc->opa;
62     glyph_dsc.bg_coords = NULL;
63     glyph_dsc.color = dsc->color;
64     glyph_dsc.rotation = dsc->rotation;
65     glyph_dsc.pivot = dsc->pivot;
66 
67     LV_PROFILER_BEGIN;
68     lv_draw_unit_draw_letter(draw_unit, &glyph_dsc, &(lv_point_t) {
69         .x = coords->x1, .y = coords->y1
70     },
71     dsc->font, dsc->unicode, draw_letter_cb);
72     LV_PROFILER_END;
73 
74     if(glyph_dsc._draw_buf) {
75         lv_draw_buf_destroy(glyph_dsc._draw_buf);
76         glyph_dsc._draw_buf = NULL;
77     }
78 }
79 
lv_draw_sw_label(lv_draw_unit_t * draw_unit,const lv_draw_label_dsc_t * dsc,const lv_area_t * coords)80 void lv_draw_sw_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords)
81 {
82     if(dsc->opa <= LV_OPA_MIN) return;
83 
84     LV_PROFILER_DRAW_BEGIN;
85     lv_draw_label_iterate_characters(draw_unit, dsc, coords, draw_letter_cb);
86     LV_PROFILER_DRAW_END;
87 }
88 
89 /**********************
90  *   STATIC FUNCTIONS
91  **********************/
92 
draw_letter_cb(lv_draw_unit_t * draw_unit,lv_draw_glyph_dsc_t * glyph_draw_dsc,lv_draw_fill_dsc_t * fill_draw_dsc,const lv_area_t * fill_area)93 static void LV_ATTRIBUTE_FAST_MEM draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc,
94                                                  lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area)
95 {
96     if(glyph_draw_dsc) {
97         switch(glyph_draw_dsc->format) {
98             case LV_FONT_GLYPH_FORMAT_NONE: {
99 #if LV_USE_FONT_PLACEHOLDER
100                     /* Draw a placeholder rectangle*/
101                     lv_draw_border_dsc_t border_draw_dsc;
102                     lv_draw_border_dsc_init(&border_draw_dsc);
103                     border_draw_dsc.opa = glyph_draw_dsc->opa;
104                     border_draw_dsc.color = glyph_draw_dsc->color;
105                     border_draw_dsc.width = 1;
106                     lv_draw_sw_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
107 #endif
108                 }
109                 break;
110             case LV_FONT_GLYPH_FORMAT_A1:
111             case LV_FONT_GLYPH_FORMAT_A2:
112             case LV_FONT_GLYPH_FORMAT_A3:
113             case LV_FONT_GLYPH_FORMAT_A4:
114             case LV_FONT_GLYPH_FORMAT_A8:
115             case LV_FONT_GLYPH_FORMAT_A1_ALIGNED:
116             case LV_FONT_GLYPH_FORMAT_A2_ALIGNED:
117             case LV_FONT_GLYPH_FORMAT_A4_ALIGNED:
118             case LV_FONT_GLYPH_FORMAT_A8_ALIGNED:
119             case LV_FONT_GLYPH_FORMAT_IMAGE: {
120                     if(glyph_draw_dsc->rotation % 3600 == 0 && glyph_draw_dsc->format != LV_FONT_GLYPH_FORMAT_IMAGE) {
121                         glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf);
122                         lv_area_t mask_area = *glyph_draw_dsc->letter_coords;
123                         mask_area.x2 = mask_area.x1 + lv_draw_buf_width_to_stride(lv_area_get_width(&mask_area), LV_COLOR_FORMAT_A8) - 1;
124                         lv_draw_sw_blend_dsc_t blend_dsc;
125                         lv_memzero(&blend_dsc, sizeof(blend_dsc));
126                         blend_dsc.color = glyph_draw_dsc->color;
127                         blend_dsc.opa = glyph_draw_dsc->opa;
128                         const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
129                         blend_dsc.mask_buf = draw_buf->data;
130                         blend_dsc.mask_area = &mask_area;
131                         blend_dsc.mask_stride = draw_buf->header.stride;
132                         blend_dsc.blend_area = glyph_draw_dsc->letter_coords;
133                         blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED;
134                         lv_draw_sw_blend(draw_unit, &blend_dsc);
135                     }
136                     else {
137                         glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf);
138                         lv_draw_image_dsc_t img_dsc;
139                         lv_draw_image_dsc_init(&img_dsc);
140                         img_dsc.rotation = glyph_draw_dsc->rotation;
141                         img_dsc.scale_x = LV_SCALE_NONE;
142                         img_dsc.scale_y = LV_SCALE_NONE;
143                         img_dsc.opa = glyph_draw_dsc->opa;
144                         img_dsc.src = glyph_draw_dsc->glyph_data;
145                         img_dsc.recolor = glyph_draw_dsc->color;
146                         img_dsc.pivot = (lv_point_t) {
147                             .x = glyph_draw_dsc->pivot.x,
148                             .y = glyph_draw_dsc->g->box_h + glyph_draw_dsc->g->ofs_y
149                         };
150                         lv_draw_sw_image(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
151                     }
152                     break;
153                 }
154             default:
155                 break;
156         }
157     }
158 
159     if(fill_draw_dsc && fill_area) {
160         lv_draw_sw_fill(draw_unit, fill_draw_dsc, fill_area);
161     }
162 }
163 
164 #endif /*LV_USE_DRAW_SW*/
165