├── LICENSE ├── README.md ├── font_asc.h ├── modframebuf-1.19.1.c └── modframebuf.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 wangshujun-tj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | mpy fb增强代码 2 | 3 | 2023.3.4修改 4 | 1、增加单色驱动的字节格式,单色,gs2,gs4都支持字节顺序和水平垂直排列 5 | 2、增加了总体的x,y镜像,和数据移动方式的操作,使得不借助屏幕硬件就能实现任意方向的旋转 6 | 3、彩色显示增加了RGB888/RGB8888 7 | 4、增加了一个比较新型的仿电子纸屏幕的驱动 8 | 5、从官方版本引入了椭圆、多边形和新版的bilt。 9 | 6、增加了ToGBK方法,可以获得utf8字符串的gb2312/gbk字符串。 10 | b=lcd.ToGBK("Micro python中文甒甒") 11 | 输入参数是utf8的字符串 12 | 输出是gb或者gbk的字符串,支持中英文混合串 13 | 7、增加了曲线函数curve,接收一个数组绘制曲线 14 | lcd.curve(buf,mode,col,x0,y0,x_scale,y_scale) 15 | buf输入的数组,支持bytearray,array的B/b/H/h共计5种格式 16 | mode显示模式,0-点,1-线,2-从x0到目标的线,默认值为0 17 | x0,y0绘制的0点,默认值为高宽值的一半 18 | x_scale,每一个和上一个点的横向移动距离,默认1 19 | y_scale,数据在y轴上的高度,默认是高度的一半 20 | 8、增加了gs2/gs4/gs8的bmp读写操作。 21 | 9、修正了单色bmp文件显示非整数宽度的错误。 22 | 10、调整0x00的字体为5*7点阵,占用6*8的显示空间 23 | 24 | 编译固件直接把两个文件复制到extmod目录即可 25 | 26 | font_asc.h是英文字库的文件,包括4种尺寸的合计12个字体数组。 27 | 28 | modframebuf.c是修改后的代码,相比于原本的版本增加了以下几个函数: 29 | 30 | 修改了text显示函数,画字符功能增加了字体和放大等功能的处理,处理串里面的utf8字符,判定是asc字符还是其他字符,asc字符调用getasc获取asc字模,其他字符调用gethzk获取字模。 31 | 配套功能font_load,告知fb组件需要使用的字库文件,不声明文件时,英文仍然可以正常显示,中文会被跳过。font_free是解除字库文件。 32 | font_set用于设置字体大小、旋转、放大和反白。 33 | 34 | 增加了show_bmp,用于处理rgb格式或者二值格式的bmp文件显示。 35 | 增加了save_bmp,用于处理rgb格式或者二值格式的fb内容保存成bmp文件。 36 | 37 | modframebuf.c 和 font_asc.h复制到extmod目录 38 | 39 | 然后直接按照原本的编译方式就可以工作了 40 | 41 | 测试过esp32,esp8266,stm32f407都是可以工作的 42 | 43 | 增加的英文字库差不多有100k,程序代码增加约20k,编译不能通过的时候注意调整程序空间的大小,比如512kflash的芯片,默认配置都是不够用的 44 | -------------------------------------------------------------------------------- /modframebuf-1.19.1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "py/runtime.h" 32 | #include "py/stream.h" 33 | #include "py/reader.h" 34 | #include "extmod/vfs.h" 35 | 36 | #if MICROPY_PY_FRAMEBUF 37 | 38 | #include "extmod/font_asc.h" 39 | 40 | 41 | typedef struct _font_set_t{ 42 | uint8_t f_style; 43 | uint8_t rotate; //xuanzhuan 44 | uint8_t scale; //fangda 16jinzhi ,gaowei hengxiang diweizongxiang 45 | uint8_t inverse; //fanbai 46 | uint16_t bg_col; 47 | }font_set_t; 48 | 49 | typedef struct _font_inf_t{ 50 | uint32_t Font_Type; //1 GB2312,2 GB18030,3 small font ,0 None font 51 | uint32_t Base_Addr12; //xuanzhuan 0,12dot font no exist 52 | uint32_t Base_Addr16; //xuanzhuan 0,16dot font no exist 53 | uint32_t Base_Addr24; //xuanzhuan 0,24dot font no exist 54 | uint32_t Base_Addr32; //xuanzhuan 0,32dot font no exist 55 | }font_inf_t; 56 | 57 | typedef struct _mp_obj_framebuf_t { 58 | mp_obj_base_t base; 59 | mp_obj_t buf_obj; // need to store this to prevent GC from reclaiming buf 60 | mp_obj_t font_file; 61 | font_set_t font_set; 62 | font_inf_t font_inf; 63 | void *buf; 64 | uint16_t width, height, stride; 65 | uint8_t format; 66 | } mp_obj_framebuf_t; 67 | 68 | #if !MICROPY_ENABLE_DYNRUNTIME 69 | STATIC const mp_obj_type_t mp_type_framebuf; 70 | #endif 71 | 72 | typedef void (*setpixel_t)(const mp_obj_framebuf_t *, int, int, uint32_t); 73 | typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t *, int, int); 74 | typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, int, int, int, int, uint32_t); 75 | 76 | typedef struct _mp_framebuf_p_t { 77 | setpixel_t setpixel; 78 | getpixel_t getpixel; 79 | fill_rect_t fill_rect; 80 | } mp_framebuf_p_t; 81 | 82 | // constants for formats 83 | #define FRAMEBUF_MVLSB (0) 84 | #define FRAMEBUF_RGB565 (1) 85 | #define FRAMEBUF_GS2_HMSB (5) 86 | #define FRAMEBUF_GS4_HMSB (2) 87 | #define FRAMEBUF_GS8 (6) 88 | #define FRAMEBUF_MHLSB (3) 89 | #define FRAMEBUF_MHMSB (4) 90 | #define FRAMEBUF_RGB565SW (7) 91 | 92 | // constants for formats 93 | #define Font_S12 (0x11) 94 | #define Font_C12 (0x21) 95 | #define Font_A12 (0x31) 96 | #define Font_R12 (0x41) 97 | 98 | #define Font_S16 (0x12) 99 | #define Font_C16 (0x22) 100 | #define Font_A16 (0x32) 101 | #define Font_R16 (0x42) 102 | 103 | #define Font_S24 (0x13) 104 | #define Font_C24 (0x23) 105 | #define Font_A24 (0x33) 106 | #define Font_R24 (0x43) 107 | 108 | #define Font_S32 (0x14) 109 | #define Font_C32 (0x24) 110 | #define Font_A32 (0x34) 111 | #define Font_R32 (0x44) 112 | 113 | mp_uint_t f_seek(mp_obj_t filename, mp_uint_t offset,mp_uint_t whence) { 114 | struct mp_stream_seek_t seek_s; 115 | 116 | seek_s.offset = offset; 117 | seek_s.whence = whence; 118 | 119 | // In POSIX, it's error to seek before end of stream, we enforce it here. 120 | if (seek_s.whence == SEEK_SET && seek_s.offset < 0) { 121 | mp_raise_OSError(MP_EINVAL); 122 | } 123 | 124 | const mp_stream_p_t *stream_p = mp_get_stream(filename); 125 | int error; 126 | mp_uint_t res = stream_p->ioctl(filename, MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error); 127 | if (res == MP_STREAM_ERROR) { 128 | mp_raise_OSError(error); 129 | } 130 | 131 | return seek_s.offset; 132 | } 133 | 134 | STATIC mp_obj_t framebuf_font_load(mp_obj_t self_in, mp_obj_t name_in) { 135 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 136 | const char *filename = mp_obj_str_get_str(name_in); 137 | //mp_printf(&mp_plat_print,"%s\n\r",filename); 138 | mp_obj_t f_args[2] = { 139 | mp_obj_new_str(filename, strlen(filename)), 140 | MP_OBJ_NEW_QSTR(MP_QSTR_rb), 141 | }; 142 | self->font_file = mp_vfs_open(MP_ARRAY_SIZE(f_args), &f_args[0], (mp_map_t *)&mp_const_empty_map); 143 | f_seek(self->font_file, 32,SEEK_SET); 144 | int errcode; 145 | int len=mp_stream_rw(self->font_file ,&self->font_inf, 20, &errcode, MP_STREAM_RW_READ); 146 | if (errcode != 0 && len!=20) { 147 | mp_raise_OSError(errcode); 148 | memset(&self->font_inf,0,20); 149 | self->font_file=NULL; 150 | mp_printf(&mp_plat_print,"Read %s error!\n\r",filename); 151 | } 152 | return mp_const_none; 153 | } 154 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_font_load_obj, framebuf_font_load); 155 | 156 | STATIC mp_obj_t framebuf_font_free(mp_obj_t self_in) { 157 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 158 | if (self->font_file != NULL){ 159 | mp_stream_close(self->font_file); 160 | mp_printf(&mp_plat_print,"font file close \n\r"); 161 | self->font_file=NULL; 162 | } 163 | return mp_const_none; 164 | } 165 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(framebuf_font_free_obj, framebuf_font_free); 166 | 167 | // Functions for MHLSB and MHMSB 168 | 169 | STATIC mp_obj_t framebuf_font_set(size_t n_args, const mp_obj_t *args) { 170 | (void)n_args; 171 | uint8_t prompt=0; 172 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 173 | mp_int_t style = mp_obj_get_int(args[1]); 174 | mp_int_t rotate =0; 175 | if (n_args > 2) { 176 | rotate = mp_obj_get_int(args[2]); 177 | } 178 | mp_int_t scale=1; 179 | if (n_args > 3) { 180 | scale = mp_obj_get_int(args[3]); 181 | } 182 | mp_int_t inverse =0; 183 | if (n_args > 4) { 184 | inverse = mp_obj_get_int(args[4]); 185 | } 186 | mp_int_t bg_col =0; 187 | if (n_args > 5) { 188 | bg_col = mp_obj_get_int(args[5]); 189 | } 190 | if ((style&0x0f)>4) { 191 | style=0x11; 192 | prompt=1; 193 | } 194 | self->font_set.f_style=style; 195 | 196 | if (scale==0){ 197 | scale=1; 198 | prompt=1; 199 | } 200 | if (scale>4){ 201 | scale=4; 202 | prompt=1; 203 | } 204 | self->font_set.scale=scale; 205 | 206 | if (rotate>3){ 207 | rotate=3; 208 | prompt=1; 209 | } 210 | self->font_set.rotate=rotate; 211 | if (inverse>1){ 212 | inverse=1; 213 | prompt=1; 214 | } 215 | self->font_set.inverse=inverse; 216 | self->font_set.bg_col=bg_col; 217 | if (prompt==1){ 218 | mp_printf(&mp_plat_print,"style=%d,rotate=%d,scale=%d,inverse=%d,bg_col=%d\n\r",self->font_set.f_style,self->font_set.rotate,self->font_set.scale,self->font_set.inverse,self->font_set.bg_col); 219 | } 220 | return mp_const_none; 221 | } 222 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_font_set_obj, 2, 6, framebuf_font_set); 223 | 224 | 225 | 226 | STATIC void mono_horiz_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 227 | size_t index = (x + y * fb->stride) >> 3; 228 | int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07); 229 | ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset); 230 | } 231 | 232 | STATIC uint32_t mono_horiz_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 233 | size_t index = (x + y * fb->stride) >> 3; 234 | int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07); 235 | return (((uint8_t *)fb->buf)[index] >> (offset)) & 0x01; 236 | } 237 | 238 | STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 239 | int reverse = fb->format == FRAMEBUF_MHMSB; 240 | int advance = fb->stride >> 3; 241 | while (w--) { 242 | uint8_t *b = &((uint8_t *)fb->buf)[(x >> 3) + y * advance]; 243 | int offset = reverse ? x & 7 : 7 - (x & 7); 244 | for (int hh = h; hh; --hh) { 245 | *b = (*b & ~(0x01 << offset)) | ((col != 0) << offset); 246 | b += advance; 247 | } 248 | ++x; 249 | } 250 | } 251 | 252 | // Functions for MVLSB format 253 | 254 | STATIC void mvlsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 255 | size_t index = (y >> 3) * fb->stride + x; 256 | uint8_t offset = y & 0x07; 257 | ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset); 258 | } 259 | 260 | STATIC uint32_t mvlsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 261 | return (((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x] >> (y & 0x07)) & 0x01; 262 | } 263 | 264 | STATIC void mvlsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 265 | while (h--) { 266 | uint8_t *b = &((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x]; 267 | uint8_t offset = y & 0x07; 268 | for (int ww = w; ww; --ww) { 269 | *b = (*b & ~(0x01 << offset)) | ((col != 0) << offset); 270 | ++b; 271 | } 272 | ++y; 273 | } 274 | } 275 | 276 | // Functions for RGB565 format 277 | 278 | STATIC void rgb565_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 279 | ((uint16_t *)fb->buf)[x + y * fb->stride] = col; 280 | } 281 | STATIC void rgb565sw_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 282 | uint32_t swap_byte; 283 | swap_byte=(col>>8)&0xff; 284 | swap_byte|=(col&0xff)<<8; 285 | ((uint16_t *)fb->buf)[x + y * fb->stride] = swap_byte; 286 | } 287 | 288 | 289 | 290 | STATIC uint32_t rgb565_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 291 | return ((uint16_t *)fb->buf)[x + y * fb->stride]; 292 | } 293 | STATIC uint32_t rgb565sw_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 294 | uint32_t swap_byte,col; 295 | col=((uint16_t *)fb->buf)[x + y * fb->stride]; 296 | swap_byte=(col>>8)&0xff; 297 | swap_byte|=(col&0xff)<<8; 298 | return swap_byte; 299 | } 300 | 301 | STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 302 | uint16_t *b = &((uint16_t *)fb->buf)[x + y * fb->stride]; 303 | while (h--) { 304 | for (int ww = w; ww; --ww) { 305 | *b++ = col; 306 | } 307 | b += fb->stride - w; 308 | } 309 | } 310 | 311 | STATIC void rgb565sw_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 312 | uint32_t swap_byte; 313 | swap_byte=(col>>8)&0xff; 314 | swap_byte|=(col&0xff)<<8; 315 | uint16_t *b = &((uint16_t *)fb->buf)[x + y * fb->stride]; 316 | while (h--) { 317 | for (int ww = w; ww; --ww) { 318 | *b++ = swap_byte; 319 | } 320 | b += fb->stride - w; 321 | } 322 | } 323 | 324 | 325 | // Functions for GS2_HMSB format 326 | 327 | STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 328 | uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2]; 329 | uint8_t shift = (x & 0x3) << 1; 330 | uint8_t mask = 0x3 << shift; 331 | uint8_t color = (col & 0x3) << shift; 332 | *pixel = color | (*pixel & (~mask)); 333 | } 334 | 335 | STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 336 | uint8_t pixel = ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2]; 337 | uint8_t shift = (x & 0x3) << 1; 338 | return (pixel >> shift) & 0x3; 339 | } 340 | 341 | STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 342 | for (int xx = x; xx < x + w; xx++) { 343 | for (int yy = y; yy < y + h; yy++) { 344 | gs2_hmsb_setpixel(fb, xx, yy, col); 345 | } 346 | } 347 | } 348 | 349 | // Functions for GS4_HMSB format 350 | 351 | STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 352 | uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1]; 353 | 354 | if (x % 2) { 355 | *pixel = ((uint8_t)col & 0x0f) | (*pixel & 0xf0); 356 | } else { 357 | *pixel = ((uint8_t)col << 4) | (*pixel & 0x0f); 358 | } 359 | } 360 | 361 | STATIC uint32_t gs4_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 362 | if (x % 2) { 363 | return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] & 0x0f; 364 | } 365 | 366 | return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] >> 4; 367 | } 368 | 369 | STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 370 | col &= 0x0f; 371 | uint8_t *pixel_pair = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1]; 372 | uint8_t col_shifted_left = col << 4; 373 | uint8_t col_pixel_pair = col_shifted_left | col; 374 | int pixel_count_till_next_line = (fb->stride - w) >> 1; 375 | bool odd_x = (x % 2 == 1); 376 | 377 | while (h--) { 378 | int ww = w; 379 | 380 | if (odd_x && ww > 0) { 381 | *pixel_pair = (*pixel_pair & 0xf0) | col; 382 | pixel_pair++; 383 | ww--; 384 | } 385 | 386 | memset(pixel_pair, col_pixel_pair, ww >> 1); 387 | pixel_pair += ww >> 1; 388 | 389 | if (ww % 2) { 390 | *pixel_pair = col_shifted_left | (*pixel_pair & 0x0f); 391 | if (!odd_x) { 392 | pixel_pair++; 393 | } 394 | } 395 | 396 | pixel_pair += pixel_count_till_next_line; 397 | } 398 | } 399 | 400 | // Functions for GS8 format 401 | 402 | STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 403 | uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)]; 404 | *pixel = col & 0xff; 405 | } 406 | 407 | STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 408 | return ((uint8_t *)fb->buf)[(x + y * fb->stride)]; 409 | } 410 | 411 | STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 412 | uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)]; 413 | while (h--) { 414 | memset(pixel, col, w); 415 | pixel += fb->stride; 416 | } 417 | } 418 | 419 | STATIC mp_framebuf_p_t formats[] = { 420 | [FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect}, 421 | [FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect}, 422 | [FRAMEBUF_RGB565SW] = {rgb565sw_setpixel, rgb565sw_getpixel, rgb565sw_fill_rect}, 423 | [FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect}, 424 | [FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect}, 425 | [FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect}, 426 | [FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, 427 | [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, 428 | }; 429 | 430 | static inline void setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 431 | if (x>=0 && xwidth && y>=0 && yheight) 432 | formats[fb->format].setpixel(fb, x, y, col); 433 | } 434 | 435 | 436 | static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 437 | return formats[fb->format].getpixel(fb, x, y); 438 | } 439 | 440 | STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 441 | if (h < 1 || w < 1 || x + w <= 0 || y + h <= 0 || y >= fb->height || x >= fb->width) { 442 | // No operation needed. 443 | return; 444 | } 445 | 446 | // clip to the framebuffer 447 | int xend = MIN(fb->width, x + w); 448 | int yend = MIN(fb->height, y + h); 449 | x = MAX(x, 0); 450 | y = MAX(y, 0); 451 | 452 | formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col); 453 | } 454 | 455 | 456 | 457 | 458 | STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { 459 | mp_arg_check_num(n_args, n_kw, 4, 5, false); 460 | 461 | mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t); 462 | o->base.type = type; 463 | o->buf_obj = args[0]; 464 | 465 | mp_buffer_info_t bufinfo; 466 | mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE); 467 | o->buf = bufinfo.buf; 468 | 469 | o->width = mp_obj_get_int(args[1]); 470 | o->height = mp_obj_get_int(args[2]); 471 | o->format = mp_obj_get_int(args[3]); 472 | if (n_args >= 5) { 473 | o->stride = mp_obj_get_int(args[4]); 474 | } else { 475 | o->stride = o->width; 476 | } 477 | //font style seting 478 | o->font_set.f_style=0x11; 479 | o->font_set.scale=1; 480 | o->font_set.rotate=0; 481 | o->font_set.inverse=0; 482 | o->font_file=NULL; 483 | o->font_inf.Font_Type=0; 484 | o->font_inf.Base_Addr12=0; //xuanzhuan 0,12dot font no exist 485 | o->font_inf.Base_Addr16=0; //xuanzhuan 0,16dot font no exist 486 | o->font_inf.Base_Addr24=0; //xuanzhuan 0,24dot font no exist 487 | o->font_inf.Base_Addr32=0; //xuanzhuan 0,32dot font no exist 488 | 489 | switch (o->format) { 490 | case FRAMEBUF_MVLSB: 491 | case FRAMEBUF_RGB565: 492 | case FRAMEBUF_RGB565SW: 493 | break; 494 | case FRAMEBUF_MHLSB: 495 | case FRAMEBUF_MHMSB: 496 | o->stride = (o->stride + 7) & ~7; 497 | break; 498 | case FRAMEBUF_GS2_HMSB: 499 | o->stride = (o->stride + 3) & ~3; 500 | break; 501 | case FRAMEBUF_GS4_HMSB: 502 | o->stride = (o->stride + 1) & ~1; 503 | break; 504 | case FRAMEBUF_GS8: 505 | break; 506 | default: 507 | mp_raise_ValueError(MP_ERROR_TEXT("invalid format")); 508 | } 509 | 510 | return MP_OBJ_FROM_PTR(o); 511 | } 512 | 513 | STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { 514 | (void)flags; 515 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 516 | bufinfo->buf = self->buf; 517 | bufinfo->len = self->stride * self->height * (self->format == FRAMEBUF_RGB565 ? 2 : 1); 518 | bufinfo->typecode = 'B'; // view framebuf as bytes 519 | return 0; 520 | } 521 | 522 | STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) { 523 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 524 | mp_int_t col = mp_obj_get_int(col_in); 525 | formats[self->format].fill_rect(self, 0, 0, self->width, self->height, col); 526 | return mp_const_none; 527 | } 528 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill); 529 | 530 | STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args) { 531 | (void)n_args; 532 | 533 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 534 | mp_int_t x = mp_obj_get_int(args[1]); 535 | mp_int_t y = mp_obj_get_int(args[2]); 536 | mp_int_t width = mp_obj_get_int(args[3]); 537 | mp_int_t height = mp_obj_get_int(args[4]); 538 | mp_int_t col = mp_obj_get_int(args[5]); 539 | 540 | fill_rect(self, x, y, width, height, col); 541 | 542 | return mp_const_none; 543 | } 544 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect); 545 | 546 | STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) { 547 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 548 | mp_int_t x = mp_obj_get_int(args[1]); 549 | mp_int_t y = mp_obj_get_int(args[2]); 550 | if (0 <= x && x < self->width && 0 <= y && y < self->height) { 551 | if (n_args == 3) { 552 | // get 553 | return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y)); 554 | } else { 555 | // set 556 | setpixel(self, x, y, mp_obj_get_int(args[3])); 557 | } 558 | } 559 | return mp_const_none; 560 | } 561 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel); 562 | 563 | STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args) { 564 | (void)n_args; 565 | 566 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 567 | mp_int_t x = mp_obj_get_int(args[1]); 568 | mp_int_t y = mp_obj_get_int(args[2]); 569 | mp_int_t w = mp_obj_get_int(args[3]); 570 | mp_int_t col = mp_obj_get_int(args[4]); 571 | 572 | fill_rect(self, x, y, w, 1, col); 573 | 574 | return mp_const_none; 575 | } 576 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline); 577 | 578 | STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args) { 579 | (void)n_args; 580 | 581 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 582 | mp_int_t x = mp_obj_get_int(args[1]); 583 | mp_int_t y = mp_obj_get_int(args[2]); 584 | mp_int_t h = mp_obj_get_int(args[3]); 585 | mp_int_t col = mp_obj_get_int(args[4]); 586 | 587 | fill_rect(self, x, y, 1, h, col); 588 | 589 | return mp_const_none; 590 | } 591 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline); 592 | 593 | STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) { 594 | (void)n_args; 595 | 596 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 597 | mp_int_t x = mp_obj_get_int(args[1]); 598 | mp_int_t y = mp_obj_get_int(args[2]); 599 | mp_int_t w = mp_obj_get_int(args[3]); 600 | mp_int_t h = mp_obj_get_int(args[4]); 601 | mp_int_t col = mp_obj_get_int(args[5]); 602 | 603 | fill_rect(self, x, y, w, 1, col); 604 | fill_rect(self, x, y + h - 1, w, 1, col); 605 | fill_rect(self, x, y, 1, h, col); 606 | fill_rect(self, x + w - 1, y, 1, h, col); 607 | 608 | return mp_const_none; 609 | } 610 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect); 611 | 612 | STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) { 613 | (void)n_args; 614 | 615 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 616 | mp_int_t x1 = mp_obj_get_int(args[1]); 617 | mp_int_t y1 = mp_obj_get_int(args[2]); 618 | mp_int_t x2 = mp_obj_get_int(args[3]); 619 | mp_int_t y2 = mp_obj_get_int(args[4]); 620 | mp_int_t col = mp_obj_get_int(args[5]); 621 | 622 | mp_int_t dx = x2 - x1; 623 | mp_int_t sx; 624 | if (dx > 0) { 625 | sx = 1; 626 | } else { 627 | dx = -dx; 628 | sx = -1; 629 | } 630 | 631 | mp_int_t dy = y2 - y1; 632 | mp_int_t sy; 633 | if (dy > 0) { 634 | sy = 1; 635 | } else { 636 | dy = -dy; 637 | sy = -1; 638 | } 639 | 640 | bool steep; 641 | if (dy > dx) { 642 | mp_int_t temp; 643 | temp = x1; 644 | x1 = y1; 645 | y1 = temp; 646 | temp = dx; 647 | dx = dy; 648 | dy = temp; 649 | temp = sx; 650 | sx = sy; 651 | sy = temp; 652 | steep = true; 653 | } else { 654 | steep = false; 655 | } 656 | 657 | mp_int_t e = 2 * dy - dx; 658 | for (mp_int_t i = 0; i < dx; ++i) { 659 | if (steep) { 660 | if (0 <= y1 && y1 < self->width && 0 <= x1 && x1 < self->height) { 661 | setpixel(self, y1, x1, col); 662 | } 663 | } else { 664 | if (0 <= x1 && x1 < self->width && 0 <= y1 && y1 < self->height) { 665 | setpixel(self, x1, y1, col); 666 | } 667 | } 668 | while (e >= 0) { 669 | y1 += sy; 670 | e -= 2 * dx; 671 | } 672 | x1 += sx; 673 | e += 2 * dy; 674 | } 675 | 676 | if (0 <= x2 && x2 < self->width && 0 <= y2 && y2 < self->height) { 677 | setpixel(self, x2, y2, col); 678 | } 679 | 680 | return mp_const_none; 681 | } 682 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line); 683 | 684 | 685 | STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) { 686 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 687 | mp_obj_t source_in = mp_obj_cast_to_native_base(args[1], MP_OBJ_FROM_PTR(&mp_type_framebuf)); 688 | if (source_in == MP_OBJ_NULL) { 689 | mp_raise_TypeError(NULL); 690 | } 691 | mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(source_in); 692 | 693 | mp_int_t x = mp_obj_get_int(args[2]); 694 | mp_int_t y = mp_obj_get_int(args[3]); 695 | mp_int_t key = -1; 696 | if (n_args > 4) { 697 | key = mp_obj_get_int(args[4]); 698 | } 699 | mp_obj_framebuf_t *palette = NULL; 700 | if (n_args > 5 && args[5] != mp_const_none) { 701 | palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf))); 702 | } 703 | 704 | if ( 705 | (x >= self->width) || 706 | (y >= self->height) || 707 | (-x >= source->width) || 708 | (-y >= source->height) 709 | ) { 710 | // Out of bounds, no-op. 711 | return mp_const_none; 712 | } 713 | 714 | // Clip. 715 | int x0 = MAX(0, x); 716 | int y0 = MAX(0, y); 717 | int x1 = MAX(0, -x); 718 | int y1 = MAX(0, -y); 719 | int x0end = MIN(self->width, x + source->width); 720 | int y0end = MIN(self->height, y + source->height); 721 | 722 | for (; y0 < y0end; ++y0) { 723 | int cx1 = x1; 724 | for (int cx0 = x0; cx0 < x0end; ++cx0) { 725 | uint32_t col = getpixel(source, cx1, y1); 726 | if (palette) { 727 | col = getpixel(palette, col, 0); 728 | } 729 | if (col != (uint32_t)key) { 730 | setpixel(self, cx0, y0, col); 731 | } 732 | ++cx1; 733 | } 734 | ++y1; 735 | } 736 | return mp_const_none; 737 | } 738 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 6, framebuf_blit); 739 | 740 | STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ystep_in) { 741 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 742 | mp_int_t xstep = mp_obj_get_int(xstep_in); 743 | mp_int_t ystep = mp_obj_get_int(ystep_in); 744 | int sx, y, xend, yend, dx, dy; 745 | if (xstep < 0) { 746 | sx = 0; 747 | xend = self->width + xstep; 748 | dx = 1; 749 | } else { 750 | sx = self->width - 1; 751 | xend = xstep - 1; 752 | dx = -1; 753 | } 754 | if (ystep < 0) { 755 | y = 0; 756 | yend = self->height + ystep; 757 | dy = 1; 758 | } else { 759 | y = self->height - 1; 760 | yend = ystep - 1; 761 | dy = -1; 762 | } 763 | for (; y != yend; y += dy) { 764 | for (int x = sx; x != xend; x += dx) { 765 | setpixel(self, x, y, getpixel(self, x - xstep, y - ystep)); 766 | } 767 | } 768 | return mp_const_none; 769 | } 770 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll); 771 | 772 | 773 | uint32_t gethzk(mp_obj_framebuf_t *self,uint32_t unicode,uint8_t * chr_data,uint8_t * font_width,uint8_t * font_high,uint8_t * font_stride){ 774 | uint8_t gbk[2]; 775 | int len; 776 | uint32_t font_index,code_index; 777 | int errcode; 778 | 779 | switch(self->font_inf.Font_Type){ 780 | case 0x0: 781 | return 1; 782 | break; 783 | case 0x1: //gb2312 784 | case 0x2: //gbk 785 | //printf("unicode to gbk or gb2312\r\n"); 786 | if ((unicode>=0x000080) && (unicode<=0x00047f)){ 787 | code_index= unicode-0x80 ; 788 | }else if ((unicode>=0x004e00) && (unicode<=0x009fa5)){ 789 | code_index= unicode-0x4e00+0x0d00; 790 | }else if ((unicode>=0x00ff00) && (unicode<=0x010000)){ 791 | code_index= unicode-0xff00+0x0C00; 792 | }else if ((unicode>=0x003000) && (unicode<=0x0030ff)){ 793 | code_index= unicode-0x3000+0x0B00; 794 | }else if ((unicode>=0x002000) && (unicode<=0x0026ff)){ 795 | code_index= unicode-0x2000+0x0400; 796 | }else{ 797 | return 2; 798 | } 799 | f_seek(self->font_file, code_index *2+0x100,SEEK_SET); 800 | len=mp_stream_rw(self->font_file ,gbk,2, &errcode, MP_STREAM_RW_READ); 801 | if (len!=2 && errcode!=0) return 3; 802 | if (self->font_inf.Font_Type==1){ 803 | if (gbk[0]>=0xa1 && gbk[0]<=0xa9 && gbk[1]>=0xa1 && gbk[1]<=0xfe ){ 804 | font_index=(gbk[0]-0xa1)*94+gbk[1]-0xa1; 805 | } else if (gbk[0]>=0xb0 && gbk[0]<=0xf7 && gbk[1]>=0xa1 && gbk[1]<=0xfe ){ 806 | font_index=(gbk[0]-0xb0)*94+gbk[1]-0xa1+846; 807 | } else { return 4; } 808 | }else if (self->font_inf.Font_Type==2){ 809 | if(gbk[0]>=0x81 && gbk[0]<=0xfe && gbk[1]>=40 && gbk[1]<=0xfe){ 810 | if(gbk[1]==0x7f) return 1; 811 | if(gbk[1]>0x7f) gbk[1]-=1; 812 | font_index=(gbk[0]-0x81)*190+gbk[1]-0x40; 813 | }else{ return 4; } 814 | }else{ return 4; } 815 | //mp_printf(&mp_plat_print,"%8.8X",font_index); 816 | switch(self->font_set.f_style&0x0f){ 817 | case 0x1: 818 | if (self->font_inf.Base_Addr12>0){ 819 | * font_width=12; 820 | * font_high=12; 821 | * font_stride=2; 822 | f_seek(self->font_file, font_index*24+self->font_inf.Base_Addr12,SEEK_SET); 823 | int len=mp_stream_rw(self->font_file ,chr_data, 24 , &errcode, MP_STREAM_RW_READ); 824 | if (len!=24 && errcode!=0) return 5; 825 | }else { return 6; } 826 | break; 827 | case 0x2: 828 | if (self->font_inf.Base_Addr16>0){ 829 | * font_width=16; 830 | * font_high=16; 831 | * font_stride=2; 832 | f_seek(self->font_file, font_index*32+self->font_inf.Base_Addr16,SEEK_SET); 833 | int len=mp_stream_rw(self->font_file ,chr_data, 32 , &errcode, MP_STREAM_RW_READ); 834 | if (len!=32 && errcode!=0) return 5; 835 | }else { return 6; } 836 | break; 837 | case 0x3: 838 | if (self->font_inf.Base_Addr24>0){ 839 | * font_width=24; 840 | * font_high=24; 841 | * font_stride=3; 842 | f_seek(self->font_file, font_index*72+self->font_inf.Base_Addr24,SEEK_SET); 843 | int len=mp_stream_rw(self->font_file ,chr_data, 72 , &errcode, MP_STREAM_RW_READ); 844 | if (len!=72 && errcode!=0) return 5; 845 | }else { return 6; } 846 | break; 847 | case 0x4: 848 | if (self->font_inf.Base_Addr32>0){ 849 | * font_width=32; 850 | * font_high=32; 851 | * font_stride=4; 852 | f_seek(self->font_file, font_index*128+self->font_inf.Base_Addr32,SEEK_SET); 853 | int len=mp_stream_rw(self->font_file ,chr_data, 128 , &errcode, MP_STREAM_RW_READ); 854 | if (len!=128 && errcode!=0) return 5; 855 | }else { return 6; } 856 | break; 857 | default: 858 | return 7; 859 | break; 860 | } 861 | break; 862 | case 0x3: //small font 863 | switch(self->font_set.f_style&0x0f){ 864 | case 0x1: 865 | if (self->font_inf.Base_Addr12>0){ 866 | * font_width=12; 867 | * font_high=12; 868 | * font_stride=2; 869 | uint32_t font_count=0; 870 | f_seek(self->font_file, 68,SEEK_SET); 871 | int len=mp_stream_rw(self->font_file ,&font_count, 4 , &errcode, MP_STREAM_RW_READ); 872 | if (len!=4 && errcode!=0) return 5; 873 | if (font_count>1024 || font_count==0) return 5; 874 | //mp_printf(&mp_plat_print,"%d--",font_count); 875 | uint32_t font_index[font_count][2]; 876 | f_seek(self->font_file, self->font_inf.Base_Addr12,SEEK_SET); 877 | len=mp_stream_rw(self->font_file ,&font_index, font_count*8 , &errcode, MP_STREAM_RW_READ); 878 | for(int find=0;findfont_file, font_index[find][1],SEEK_SET); 881 | len=mp_stream_rw(self->font_file ,chr_data, 24 , &errcode, MP_STREAM_RW_READ); 882 | if (len!=24 && errcode!=0) { return 5;} 883 | else {return 0; } 884 | } 885 | } 886 | return 6; 887 | }else { return 6; } 888 | break; 889 | case 0x2: 890 | if (self->font_inf.Base_Addr16>0){ 891 | * font_width=16; 892 | * font_high=16; 893 | * font_stride=2; 894 | uint32_t font_count=0; 895 | f_seek(self->font_file, 72,SEEK_SET); 896 | int len=mp_stream_rw(self->font_file ,&font_count, 4 , &errcode, MP_STREAM_RW_READ); 897 | if (len!=4 && errcode!=0) return 5; 898 | if (font_count>1024 || font_count==0) return 5; 899 | uint32_t font_index[font_count][2]; 900 | f_seek(self->font_file, self->font_inf.Base_Addr16,SEEK_SET); 901 | len=mp_stream_rw(self->font_file ,&font_index, font_count*8 , &errcode, MP_STREAM_RW_READ); 902 | for(int find=0;findfont_file, font_index[find][1],SEEK_SET); 905 | len=mp_stream_rw(self->font_file ,chr_data, 32 , &errcode, MP_STREAM_RW_READ); 906 | if (len!=32 && errcode!=0) {return 5; } 907 | else {return 0; } 908 | } 909 | } 910 | return 6; 911 | }else { return 6; } 912 | break; 913 | case 0x3: 914 | if (self->font_inf.Base_Addr24>0){ 915 | * font_width=24; 916 | * font_high=24; 917 | * font_stride=3; 918 | uint32_t font_count=0; 919 | f_seek(self->font_file, 72,SEEK_SET); 920 | int len=mp_stream_rw(self->font_file ,&font_count, 4 , &errcode, MP_STREAM_RW_READ); 921 | if (len!=4 && errcode!=0) return 5; 922 | if (font_count>1024 || font_count==0) return 5; 923 | uint32_t font_index[font_count][2]; 924 | f_seek(self->font_file, self->font_inf.Base_Addr24,SEEK_SET); 925 | len=mp_stream_rw(self->font_file ,&font_index, font_count*8 , &errcode, MP_STREAM_RW_READ); 926 | for(int find=0;findfont_file, font_index[find][1],SEEK_SET); 929 | len=mp_stream_rw(self->font_file ,chr_data, 72, &errcode, MP_STREAM_RW_READ); 930 | if (len!=72 && errcode!=0) {return 5; } 931 | else {return 0; } 932 | } 933 | } 934 | return 6; 935 | }else { return 6; } 936 | break; 937 | case 0x4: 938 | if (self->font_inf.Base_Addr32>0){ 939 | * font_width=32; 940 | * font_high=32; 941 | * font_stride=4; 942 | uint32_t font_count=0; 943 | f_seek(self->font_file, 76,SEEK_SET); 944 | int len=mp_stream_rw(self->font_file ,&font_count, 4 , &errcode, MP_STREAM_RW_READ); 945 | if (len!=4 && errcode!=0) return 5; 946 | if (font_count>1024 || font_count==0) return 5; 947 | uint32_t font_index[font_count][2]; 948 | f_seek(self->font_file, self->font_inf.Base_Addr32,SEEK_SET); 949 | len=mp_stream_rw(self->font_file ,&font_index, font_count*8 , &errcode, MP_STREAM_RW_READ); 950 | for(int find=0;findfont_file, font_index[find][1],SEEK_SET); 953 | len=mp_stream_rw(self->font_file ,chr_data, 128 , &errcode, MP_STREAM_RW_READ); 954 | if (len!=128 && errcode!=0) {return 5; } 955 | else {return 0; } 956 | } 957 | } 958 | return 6; 959 | }else { return 6; } 960 | break; 961 | } 962 | break; 963 | default: 964 | return 1; 965 | break; 966 | } 967 | return 0; 968 | } 969 | 970 | 971 | uint32_t getasc(uint8_t f_style,uint8_t chr,uint8_t * chr_data,uint8_t * font_width,uint8_t * font_high,uint8_t * font_stride){ 972 | switch(f_style&0x0f){ 973 | case 0x0: 974 | * font_width=8; 975 | * font_high=8; 976 | * font_stride=1; 977 | memcpy(chr_data,&font_s_8X8[(chr - 32) * 8],8); 978 | break; 979 | case 0x1: 980 | switch((f_style>>4)&0x0f){ 981 | case 0x01: 982 | * font_width=6; 983 | * font_high=12; 984 | * font_stride=1; 985 | memcpy(chr_data,&font_s_6X12[(chr - 32) * 12],12); 986 | break; 987 | case 0x02: 988 | * font_width=6; 989 | * font_high=12; 990 | * font_stride=1; 991 | memcpy(chr_data,&font_c_6X12[(chr - 32) * 12],12); 992 | break; 993 | case 0x03: 994 | * font_width=font_a_6X12[(chr - 32) * 26+1]; 995 | * font_high=12; 996 | * font_stride=2; 997 | memcpy(chr_data,&font_a_6X12[(chr - 32) * 26+2],24); 998 | break; 999 | case 0x04: 1000 | * font_width=font_a_6X12[(chr - 32) * 26+1]; 1001 | * font_high=12; 1002 | * font_stride=2; 1003 | memcpy(chr_data,&font_r_6X12[(chr - 32) * 26+2],24); 1004 | break; 1005 | default : 1006 | return 1; 1007 | } 1008 | break; 1009 | case 0x2: 1010 | switch((f_style>>4)&0x0f){ 1011 | case 0x01: 1012 | * font_width=8; 1013 | * font_high=16; 1014 | * font_stride=1; 1015 | memcpy(chr_data,&font_s_8X16[(chr - 32) * 16],16); 1016 | break; 1017 | case 0x02: 1018 | * font_width=8; 1019 | * font_high=16; 1020 | * font_stride=1; 1021 | memcpy(chr_data,&font_c_8X16[(chr - 32) * 16],16); 1022 | break; 1023 | case 0x03: 1024 | * font_width=font_a_8X16[(chr - 32) * 34+1]; 1025 | * font_high=16; 1026 | * font_stride=2; 1027 | memcpy(chr_data,&font_a_8X16[(chr - 32) * 34+2],32); 1028 | break; 1029 | case 0x04: 1030 | * font_width=font_a_8X16[(chr - 32) * 34+1]; 1031 | * font_high=16; 1032 | * font_stride=2; 1033 | memcpy(chr_data,&font_r_8X16[(chr - 32) * 34+2],32); 1034 | break; 1035 | default : 1036 | return 1; 1037 | } 1038 | break; 1039 | case 0x3: 1040 | switch((f_style>>4)&0x0f){ 1041 | case 0x01: 1042 | * font_width=12; 1043 | * font_high=24; 1044 | * font_stride=2; 1045 | memcpy(chr_data,&font_s_12X24[(chr - 32) * 48],48); 1046 | break; 1047 | case 0x02: 1048 | * font_width=12; 1049 | * font_high=24; 1050 | * font_stride=2; 1051 | memcpy(chr_data,&font_c_12X24[(chr - 32) * 48],48); 1052 | break; 1053 | case 0x03: 1054 | * font_width=font_a_12X24[(chr - 32) * 74+1]; 1055 | * font_high=24; 1056 | * font_stride=3; 1057 | memcpy(chr_data,&font_a_12X24[(chr - 32) * 74+2],72); 1058 | break; 1059 | case 0x04: 1060 | * font_width=font_a_12X24[(chr - 32) * 74+1]; 1061 | * font_high=24; 1062 | * font_stride=3; 1063 | memcpy(chr_data,&font_r_12X24[(chr - 32) * 74+2],72); 1064 | break; 1065 | default : 1066 | return 1; 1067 | } 1068 | break; 1069 | case 0x4: 1070 | switch((f_style>>4)&0x0f){ 1071 | case 0x01: 1072 | * font_width=16; 1073 | * font_high=32; 1074 | * font_stride=2; 1075 | memcpy(chr_data,&font_s_16X32[(chr - 32) * 64],64); 1076 | break; 1077 | case 0x02: 1078 | * font_width=16; 1079 | * font_high=32; 1080 | * font_stride=2; 1081 | memcpy(chr_data,&font_c_16X32[(chr - 32) * 64],64); 1082 | break; 1083 | case 0x03: 1084 | * font_width=font_a_16X32[(chr - 32) * 130+1]; 1085 | * font_high=32; 1086 | * font_stride=4; 1087 | memcpy(chr_data,&font_a_16X32[(chr - 32) * 130+2],128); 1088 | break; 1089 | case 0x04: 1090 | * font_width=font_a_16X32[(chr - 32) * 130+1]; 1091 | * font_high=32; 1092 | * font_stride=4; 1093 | memcpy(chr_data,&font_r_16X32[(chr - 32) * 130+2],128); 1094 | break; 1095 | default : 1096 | return 1; 1097 | } 1098 | break; 1099 | default: 1100 | return 1; 1101 | } 1102 | return 0; 1103 | } 1104 | 1105 | STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) { 1106 | // extract arguments 1107 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 1108 | const char *str = mp_obj_str_get_str(args[1]); 1109 | mp_int_t x0 = mp_obj_get_int(args[2]); 1110 | mp_int_t y0 = mp_obj_get_int(args[3]); 1111 | mp_int_t col = 1; 1112 | uint8_t chr_data[130]; 1113 | uint32_t mask,unicode; 1114 | uint8_t utf8len; 1115 | uint8_t ret=1; 1116 | uint8_t font_width,font_high,font_stride=2; 1117 | if (n_args >= 5) { 1118 | col = mp_obj_get_int(args[4]); 1119 | } 1120 | 1121 | // loop over chars 1122 | for (; *str; ++str) { 1123 | // get char and make sure its in range of font 1124 | int chr = *(uint8_t *)str; 1125 | //panding tiaojian duqu yingwen he zhongwenziku 1126 | if (chr<0x80){ 1127 | if (chr < 32 || chr > 127) { 1128 | //mp_printf(&mp_plat_print,"%2.2X",chr); 1129 | continue; 1130 | } 1131 | ret=getasc(self->font_set.f_style,chr,chr_data,&font_width,&font_high,&font_stride); 1132 | 1133 | }else{ 1134 | if (chr>=0xC0 && chr<0xE0) { //2 1135 | utf8len=2; 1136 | unicode=(chr&0x1f)<<6*(utf8len-1); 1137 | }else if(chr>=0xE0 && chr<0xF0){ 1138 | utf8len=3; 1139 | unicode=(chr&0x0f)<<6*(utf8len-1); 1140 | }else if(chr>=0xF0 && chr<0xF8){ 1141 | utf8len=4; 1142 | unicode=(chr&0x07)<<6*(utf8len-1); 1143 | }else if(chr>=0xF8 && chr<0xFC){ 1144 | utf8len=5; 1145 | unicode=(chr&0x03)<<6*(utf8len-1); 1146 | }else if(chr>=0xFC){ 1147 | utf8len=6; 1148 | unicode=(chr&0x01)<<6*(utf8len-1); 1149 | }else { 1150 | unicode=0; 1151 | continue; 1152 | } 1153 | for (uint32_t i=0;ifont_set.bg_col==0){ 1172 | transparent=1; 1173 | } 1174 | mask=0x00000001<<(font_stride*8-1); 1175 | if (((self->font_set.rotate==0 ||self->font_set.rotate==2)&&(x0 + font_width*self->font_set.scale <= self->width )&&( y0 + font_high*self->font_set.scale <= self->height)) || 1176 | ((self->font_set.rotate==1 ||self->font_set.rotate==3)&&(x0 + font_high*self->font_set.scale <= self->width )&&( y0 + font_width*self->font_set.scale <= self->height))){ 1177 | for (int y = 0; y < font_high; y++){ 1178 | uint vline_data=0; 1179 | for(int k=0;k>x))&&self->font_set.inverse==0) || 1184 | ((~vline_data & (mask>>x))&&self->font_set.inverse==1)){ 1185 | // only draw if pixel set 1186 | for (int x_scale=0;x_scalefont_set.scale;x_scale++){ 1187 | for (int y_scale=0;y_scalefont_set.scale;y_scale++){ 1188 | switch(self->font_set.rotate){ 1189 | case 0: 1190 | setpixel(self, x0+x*self->font_set.scale+x_scale, y0+y*self->font_set.scale+y_scale, col); 1191 | break; 1192 | case 1: 1193 | setpixel(self, x0+font_high*self->font_set.scale-y*self->font_set.scale-y_scale, y0+x*self->font_set.scale+x_scale, col); 1194 | break; 1195 | case 2: 1196 | setpixel(self, x0+font_width*self->font_set.scale-x*self->font_set.scale-x_scale, y0+font_high*self->font_set.scale-y*self->font_set.scale-y_scale, col); 1197 | break; 1198 | case 3: 1199 | setpixel(self, x0+y*self->font_set.scale-y_scale, y0+font_width*self->font_set.scale-x*self->font_set.scale-x_scale, col); 1200 | break; 1201 | } 1202 | } 1203 | } 1204 | }else{ 1205 | if (transparent==0){ 1206 | for (int x_scale=0;x_scalefont_set.scale;x_scale++){ 1207 | for (int y_scale=0;y_scalefont_set.scale;y_scale++){ 1208 | switch(self->font_set.rotate){ 1209 | case 0: 1210 | setpixel(self, x0+x*self->font_set.scale+x_scale, y0+y*self->font_set.scale+y_scale, self->font_set.bg_col); 1211 | break; 1212 | case 1: 1213 | setpixel(self, x0+font_high*self->font_set.scale-y*self->font_set.scale-y_scale, y0+x*self->font_set.scale+x_scale, self->font_set.bg_col); 1214 | break; 1215 | case 2: 1216 | setpixel(self, x0+font_width*self->font_set.scale-x*self->font_set.scale-x_scale, y0+font_high*self->font_set.scale-y*self->font_set.scale-y_scale, self->font_set.bg_col); 1217 | break; 1218 | case 3: 1219 | setpixel(self, x0+y*self->font_set.scale-y_scale, y0+font_width*self->font_set.scale-x*self->font_set.scale-x_scale, self->font_set.bg_col); 1220 | break; 1221 | } 1222 | } 1223 | } 1224 | } 1225 | } 1226 | } 1227 | } 1228 | if ((self->font_set.rotate==0 ||self->font_set.rotate==2)){ 1229 | x0+=font_width*self->font_set.scale; 1230 | }else{ 1231 | x0+=font_high*self->font_set.scale; 1232 | } 1233 | } 1234 | } 1235 | } 1236 | return mp_const_none; 1237 | } 1238 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_text_obj, 4, 5, framebuf_text); 1239 | 1240 | 1241 | typedef struct __attribute__((packed)) tagBITMAPFILEHEADER 1242 | { 1243 | uint16_t bfType; 1244 | uint32_t bfSize; 1245 | uint16_t bfReserved1; 1246 | uint16_t bfReserved2; 1247 | uint32_t bfOffBits; 1248 | uint32_t biHSize; 1249 | uint32_t biWidth; 1250 | uint32_t biHeight; 1251 | uint16_t biPlanes; 1252 | uint16_t biBitcount; 1253 | uint16_t biComp; 1254 | uint16_t bfReserved3; 1255 | uint32_t biPSize; 1256 | 1257 | } BITMAPFILEHEADER; 1258 | 1259 | STATIC mp_obj_t framebuf_show_bmp(size_t n_args, const mp_obj_t *args) { 1260 | // extract arguments 1261 | BITMAPFILEHEADER bmp_h; 1262 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 1263 | const char *filename = mp_obj_str_get_str(args[1]); 1264 | mp_int_t x0 = 0; 1265 | mp_int_t y0 = 0; 1266 | if (n_args >= 4) { 1267 | x0 = mp_obj_get_int(args[2]); 1268 | y0 = mp_obj_get_int(args[3]); 1269 | } 1270 | mp_int_t w = self->width-x0; 1271 | mp_int_t h = self->height-y0; 1272 | if (n_args >= 6) { 1273 | w = MIN(mp_obj_get_int(args[4]),w); 1274 | h = MIN(mp_obj_get_int(args[5]),h); 1275 | } 1276 | mp_obj_t f_args[2] = { 1277 | mp_obj_new_str(filename, strlen(filename)), 1278 | MP_OBJ_NEW_QSTR(MP_QSTR_rb), 1279 | }; 1280 | //mp_printf(&mp_plat_print,"open file. \r\n"); 1281 | mp_obj_t bmp_file = mp_vfs_open(MP_ARRAY_SIZE(f_args), &f_args[0], (mp_map_t *)&mp_const_empty_map); 1282 | int errcode; 1283 | //mp_printf(&mp_plat_print,"write head. \r\n"); 1284 | 1285 | int len=mp_stream_rw(bmp_file ,&bmp_h, sizeof(BITMAPFILEHEADER), &errcode, MP_STREAM_OP_READ); 1286 | if (errcode != 0 && len!=sizeof(BITMAPFILEHEADER)) { 1287 | mp_raise_OSError(errcode); 1288 | mp_printf(&mp_plat_print,"Write %s error!\r\n",filename); 1289 | } 1290 | //mp_printf(&mp_plat_print,"%d,%d,%d,%d. \r\n",x0,y0,w,h); 1291 | //memset(&bmp_h,0,sizeof(BITMAPFILEHEADER)); 1292 | if (bmp_h.bfType!=0x4d42){ 1293 | mp_printf(&mp_plat_print,"File %s not BMP.\r\n",filename); 1294 | return mp_const_none; 1295 | } 1296 | if (self->format==FRAMEBUF_RGB565 || self->format==FRAMEBUF_RGB565SW){ 1297 | if (bmp_h.biBitcount!=0x18){ 1298 | mp_printf(&mp_plat_print,"File %s color no match.\r\n",filename); 1299 | return mp_const_none; 1300 | } 1301 | }else if(self->format==FRAMEBUF_MVLSB || self->format==FRAMEBUF_MHLSB || self->format==FRAMEBUF_MHMSB){ 1302 | if (bmp_h.biBitcount!=0x01){ 1303 | mp_printf(&mp_plat_print,"File %s color no match.\r\n",filename); 1304 | return mp_const_none; 1305 | } 1306 | }else { 1307 | mp_printf(&mp_plat_print,"Unsupported format. \r\n"); 1308 | return mp_const_none; 1309 | } 1310 | //mp_printf(&mp_plat_print,"x=%d,y=%d,w=%d,h=%d\r\n",x0,y0,w,h); 1311 | if (x0<0 && abs(x0)>bmp_h.biWidth) x0=-bmp_h.biWidth; 1312 | if (y0<0 && abs(y0)>bmp_h.biHeight) y0=-bmp_h.biHeight; 1313 | if (x0>self->width) x0=self->width; 1314 | if (y0>self->height) y0=self->height; 1315 | if (w>self->width-x0) w=self->width-x0; 1316 | if (h>self->height-y0) h=self->height-y0; 1317 | 1318 | //mp_printf(&mp_plat_print,"x=%d,y=%d,w=%d,h=%d\r\n",x0,y0,w,h); 1319 | 1320 | w=MIN(bmp_h.biWidth,w); 1321 | h=MIN(bmp_h.biHeight,h); 1322 | //mp_printf(&mp_plat_print,"x=%d,y=%d,w=%d,h=%d\r\n",x0,y0,w,h); 1323 | uint32_t stride=(bmp_h.biWidth+7)/8*8; 1324 | f_seek(bmp_file, bmp_h.bfOffBits,SEEK_SET); 1325 | 1326 | //mp_printf(&mp_plat_print,"write pixel. \r\n"); 1327 | if (self->format==FRAMEBUF_RGB565 || self->format==FRAMEBUF_RGB565SW ){ 1328 | 1329 | uint8_t line_buf[bmp_h.biWidth][3]; 1330 | int32_t hh,ww; 1331 | uint16_t dot_col; 1332 | for(hh=bmp_h.biHeight;hh;hh--){ 1333 | len=mp_stream_rw(bmp_file ,&line_buf, bmp_h.biWidth*3, &errcode, MP_STREAM_OP_READ); 1334 | for(ww=bmp_h.biWidth;ww;ww--){ 1335 | if (ww<=w && hh>3; 1337 | dot_col|=(line_buf[ww-1][1]&0xfc)<<3; 1338 | dot_col|=(line_buf[ww-1][2]&0xf8)<<8; 1339 | setpixel(self, x0+ww-1, y0+hh-1,dot_col); 1340 | } 1341 | } 1342 | if (bmp_h.biWidth%4>0) 1343 | len=mp_stream_rw(bmp_file ,&line_buf, bmp_h.biWidth%4, &errcode, MP_STREAM_OP_READ); 1344 | } 1345 | }else if(self->format==FRAMEBUF_MVLSB || self->format==FRAMEBUF_MHLSB || self->format==FRAMEBUF_MHMSB){ 1346 | uint8_t line_buf[stride/8]; 1347 | int32_t hh,ww; 1348 | for(hh=bmp_h.biHeight;hh;--hh){ 1349 | len=mp_stream_rw(bmp_file ,&line_buf, stride/8, &errcode, MP_STREAM_OP_READ); 1350 | for(ww=bmp_h.biWidth;ww;--ww){ 1351 | if (ww<=w && hh>(ww%8)))==0){ 1353 | setpixel(self, x0+ww-1, y0+hh-1,0); 1354 | }else{ 1355 | setpixel(self, x0+ww-1, y0+hh-1,1); 1356 | } 1357 | } 1358 | } 1359 | } 1360 | } 1361 | //mp_printf(&mp_plat_print,"close file. \r\n"); 1362 | mp_stream_close(bmp_file); 1363 | return mp_const_none; 1364 | } 1365 | 1366 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_show_bmp_obj, 2, 6, framebuf_show_bmp); 1367 | 1368 | 1369 | STATIC mp_obj_t framebuf_save_bmp(size_t n_args, const mp_obj_t *args) { 1370 | // extract arguments 1371 | BITMAPFILEHEADER bmp_h; 1372 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 1373 | const char *filename = mp_obj_str_get_str(args[1]); 1374 | mp_int_t x0 = 0; 1375 | mp_int_t y0 = 0; 1376 | if (n_args >= 4) { 1377 | x0 = mp_obj_get_int(args[2]); 1378 | y0 = mp_obj_get_int(args[3]); 1379 | } 1380 | mp_int_t w = self->width-x0; 1381 | mp_int_t h = self->height-y0; 1382 | if (n_args >= 6) { 1383 | w = MIN(mp_obj_get_int(args[4]),self->width-x0); 1384 | h = MIN(mp_obj_get_int(args[5]),self->height-y0); 1385 | } 1386 | uint32_t stride=(w+7)/8*8; 1387 | //mp_printf(&mp_plat_print,"%d,%d,%d,%d. \r\n",x0,y0,w,h); 1388 | memset(&bmp_h,0,sizeof(BITMAPFILEHEADER)); 1389 | bmp_h.bfType=0x4d42; 1390 | if (self->format==FRAMEBUF_RGB565 || self->format==FRAMEBUF_RGB565SW){ 1391 | bmp_h.bfOffBits=0x36;//dian zhen cun chu pian yi 1392 | bmp_h.biBitcount=0x18; 1393 | bmp_h.bfSize=56+w*h*3; //wen jian zong chi cun 1394 | bmp_h.biPSize=w*h*3; 1395 | }else if(self->format==FRAMEBUF_MVLSB || self->format==FRAMEBUF_MHLSB || self->format==FRAMEBUF_MHMSB){ 1396 | bmp_h.bfOffBits=0x3e;//dian zhen cun chu pian yi 1397 | bmp_h.biBitcount=0x01; 1398 | bmp_h.bfSize=62+stride/8*h; //wen jian zong chi cun 1399 | bmp_h.biPSize=stride/8*h; 1400 | }else { 1401 | mp_printf(&mp_plat_print,"Unsupported format. \r\n"); 1402 | return mp_const_none; 1403 | } 1404 | bmp_h.biComp=0x00; 1405 | bmp_h.biHSize=0x28; 1406 | bmp_h.biWidth=w; 1407 | bmp_h.biHeight=h; 1408 | bmp_h.biPlanes=1; 1409 | 1410 | mp_obj_t f_args[2] = { 1411 | mp_obj_new_str(filename, strlen(filename)), 1412 | MP_OBJ_NEW_QSTR(MP_QSTR_wb), 1413 | }; 1414 | //mp_printf(&mp_plat_print,"open file. \r\n"); 1415 | mp_obj_t bmp_file = mp_vfs_open(MP_ARRAY_SIZE(f_args), &f_args[0], (mp_map_t *)&mp_const_empty_map); 1416 | int errcode; 1417 | //mp_printf(&mp_plat_print,"write head. \r\n"); 1418 | int len=mp_stream_rw(bmp_file ,&bmp_h, sizeof(BITMAPFILEHEADER), &errcode, MP_STREAM_OP_WRITE); 1419 | if (errcode != 0 && len!=sizeof(BITMAPFILEHEADER)) { 1420 | mp_raise_OSError(errcode); 1421 | mp_printf(&mp_plat_print,"Write %s error!\r\n",filename); 1422 | } 1423 | uint8_t buf[bmp_h.bfOffBits-sizeof(BITMAPFILEHEADER)]; 1424 | memset(&buf,0,bmp_h.bfOffBits-sizeof(BITMAPFILEHEADER)); 1425 | buf[bmp_h.bfOffBits-sizeof(BITMAPFILEHEADER)-2]=0xff; 1426 | buf[bmp_h.bfOffBits-sizeof(BITMAPFILEHEADER)-3]=0xff; 1427 | buf[bmp_h.bfOffBits-sizeof(BITMAPFILEHEADER)-4]=0xff; 1428 | 1429 | len=mp_stream_rw(bmp_file ,&buf, bmp_h.bfOffBits-sizeof(BITMAPFILEHEADER), &errcode, MP_STREAM_OP_WRITE); 1430 | if (errcode != 0 && len!=sizeof(BITMAPFILEHEADER)) { 1431 | mp_raise_OSError(errcode); 1432 | mp_printf(&mp_plat_print,"Write %s error!\r\n",filename); 1433 | } 1434 | //mp_printf(&mp_plat_print,"write pixel. \r\n"); 1435 | if (self->format==FRAMEBUF_RGB565 || self->format==FRAMEBUF_RGB565SW ){ 1436 | uint8_t line_buf[w][3]; 1437 | uint32_t hh,ww; 1438 | uint16_t dot_col; 1439 | for(hh=h;hh;hh--){ 1440 | for(ww=w;ww;ww--){ 1441 | dot_col=getpixel(self, x0+ww-1, y0+hh-1); 1442 | //mp_printf(&mp_plat_print,"%4.4x,",dot_col); 1443 | line_buf[ww-1][2]=(dot_col&0xf800)>>8; 1444 | line_buf[ww-1][1]=(dot_col&0x07e0)>>3; 1445 | line_buf[ww-1][0]=(dot_col&0x001e)<<3; 1446 | } 1447 | len=mp_stream_rw(bmp_file ,&line_buf, w*3, &errcode, MP_STREAM_OP_WRITE); 1448 | if (w%4>0) 1449 | len=mp_stream_rw(bmp_file ,&line_buf, w%4, &errcode, MP_STREAM_OP_WRITE); 1450 | } 1451 | }else if(self->format==FRAMEBUF_MVLSB || self->format==FRAMEBUF_MHLSB || self->format==FRAMEBUF_MHMSB){ 1452 | uint8_t line_buf[stride/8]; 1453 | uint32_t hh,ww; 1454 | for(hh=h;hh;--hh){ 1455 | memset(&line_buf,0,stride/8); 1456 | for(ww=w;ww;--ww){ 1457 | if (getpixel(self, x0+ww-1, y0+hh-1)==0) 1458 | line_buf[(ww-1)/8]|=(0x80)>>((ww-1)%8); 1459 | } 1460 | len=mp_stream_rw(bmp_file ,&line_buf, stride/8, &errcode, MP_STREAM_OP_WRITE); 1461 | } 1462 | } 1463 | //mp_printf(&mp_plat_print,"close file. \r\n"); 1464 | mp_stream_close(bmp_file); 1465 | return mp_const_none; 1466 | } 1467 | 1468 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_save_bmp_obj, 2, 6, framebuf_save_bmp); 1469 | 1470 | 1471 | STATIC mp_obj_t framebuf_line_LUT(mp_obj_t self_in, mp_obj_t line, mp_obj_t lut_in) { 1472 | // 行转换,输入参数:行,查找表,返回行数据 1473 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 1474 | mp_buffer_info_t lut; 1475 | mp_get_buffer_raise(lut_in, &lut, MP_BUFFER_READ); 1476 | uint16_t line_num = mp_obj_get_int(line); 1477 | uint16_t buff[self->width]; 1478 | mp_obj_t ret_buf = mp_obj_new_bytearray(32,(uint8_t*)&buff); 1479 | uint16_t col_dot; 1480 | if (lut.len!=32) { 1481 | mp_printf(&mp_plat_print,"LUT table Error. \r\n"); 1482 | return mp_const_none; 1483 | } 1484 | if (self->format==FRAMEBUF_GS4_HMSB){ 1485 | for(int ww=0;wwwidth;ww++) 1486 | { 1487 | col_dot=getpixel(self, ww, line_num); 1488 | buff[ww] =((uint16_t *) lut.buf)[col_dot]; 1489 | } 1490 | } else{ 1491 | mp_printf(&mp_plat_print,"Only 4 bit mode is supported. \r\n"); 1492 | return mp_const_none; 1493 | } 1494 | return ret_buf; 1495 | } 1496 | 1497 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_line_LUT_obj, framebuf_line_LUT); 1498 | 1499 | 1500 | #if !MICROPY_ENABLE_DYNRUNTIME 1501 | STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = { 1502 | { MP_ROM_QSTR(MP_QSTR_show_bmp), MP_ROM_PTR(&framebuf_show_bmp_obj) }, 1503 | { MP_ROM_QSTR(MP_QSTR_save_bmp), MP_ROM_PTR(&framebuf_save_bmp_obj) }, 1504 | { MP_ROM_QSTR(MP_QSTR_font_load), MP_ROM_PTR(&framebuf_font_load_obj) }, 1505 | { MP_ROM_QSTR(MP_QSTR_font_free), MP_ROM_PTR(&framebuf_font_free_obj) }, 1506 | { MP_ROM_QSTR(MP_QSTR_font_set), MP_ROM_PTR(&framebuf_font_set_obj) }, 1507 | { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&framebuf_fill_obj) }, 1508 | { MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&framebuf_fill_rect_obj) }, 1509 | { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&framebuf_pixel_obj) }, 1510 | { MP_ROM_QSTR(MP_QSTR_hline), MP_ROM_PTR(&framebuf_hline_obj) }, 1511 | { MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) }, 1512 | { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) }, 1513 | { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) }, 1514 | { MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) }, 1515 | { MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) }, 1516 | { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) }, 1517 | { MP_ROM_QSTR(MP_QSTR_line_LUT), MP_ROM_PTR(&framebuf_line_LUT_obj) }, 1518 | }; 1519 | STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table); 1520 | 1521 | STATIC MP_DEFINE_CONST_OBJ_TYPE( 1522 | mp_type_framebuf, 1523 | MP_QSTR_FrameBuffer, 1524 | MP_TYPE_FLAG_NONE, 1525 | make_new, framebuf_make_new, 1526 | buffer, framebuf_get_buffer, 1527 | locals_dict, &framebuf_locals_dict 1528 | ); 1529 | 1530 | 1531 | #endif 1532 | 1533 | // this factory function is provided for backwards compatibility with old FrameBuffer1 class 1534 | STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) { 1535 | mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t); 1536 | o->base.type = &mp_type_framebuf; 1537 | 1538 | mp_buffer_info_t bufinfo; 1539 | mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE); 1540 | o->buf = bufinfo.buf; 1541 | 1542 | o->width = mp_obj_get_int(args[1]); 1543 | o->height = mp_obj_get_int(args[2]); 1544 | o->format = FRAMEBUF_MVLSB; 1545 | if (n_args >= 4) { 1546 | o->stride = mp_obj_get_int(args[3]); 1547 | } else { 1548 | o->stride = o->width; 1549 | } 1550 | 1551 | return MP_OBJ_FROM_PTR(o); 1552 | } 1553 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1); 1554 | 1555 | #if !MICROPY_ENABLE_DYNRUNTIME 1556 | STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = { 1557 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) }, 1558 | { MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) }, 1559 | { MP_ROM_QSTR(MP_QSTR_FrameBuffer1), MP_ROM_PTR(&legacy_framebuffer1_obj) }, 1560 | { MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) }, 1561 | { MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) }, 1562 | { MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) }, 1563 | { MP_ROM_QSTR(MP_QSTR_RGB565SW), MP_ROM_INT(FRAMEBUF_RGB565SW) }, 1564 | { MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) }, 1565 | { MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) }, 1566 | { MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) }, 1567 | { MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MHLSB) }, 1568 | { MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MHMSB) }, 1569 | 1570 | { MP_ROM_QSTR(MP_QSTR_Font_S12), MP_ROM_INT(Font_S12) }, 1571 | { MP_ROM_QSTR(MP_QSTR_Font_C12), MP_ROM_INT(Font_C12) }, 1572 | { MP_ROM_QSTR(MP_QSTR_Font_A12), MP_ROM_INT(Font_A12) }, 1573 | { MP_ROM_QSTR(MP_QSTR_Font_R12), MP_ROM_INT(Font_R12) }, 1574 | 1575 | { MP_ROM_QSTR(MP_QSTR_Font_S16), MP_ROM_INT(Font_S16) }, 1576 | { MP_ROM_QSTR(MP_QSTR_Font_C16), MP_ROM_INT(Font_C16) }, 1577 | { MP_ROM_QSTR(MP_QSTR_Font_A16), MP_ROM_INT(Font_A16) }, 1578 | { MP_ROM_QSTR(MP_QSTR_Font_R16), MP_ROM_INT(Font_R16) }, 1579 | 1580 | { MP_ROM_QSTR(MP_QSTR_Font_S24), MP_ROM_INT(Font_S24) }, 1581 | { MP_ROM_QSTR(MP_QSTR_Font_C24), MP_ROM_INT(Font_C24) }, 1582 | { MP_ROM_QSTR(MP_QSTR_Font_A24), MP_ROM_INT(Font_A24) }, 1583 | { MP_ROM_QSTR(MP_QSTR_Font_R24), MP_ROM_INT(Font_R24) }, 1584 | 1585 | { MP_ROM_QSTR(MP_QSTR_Font_S32), MP_ROM_INT(Font_S32) }, 1586 | { MP_ROM_QSTR(MP_QSTR_Font_C32), MP_ROM_INT(Font_C32) }, 1587 | { MP_ROM_QSTR(MP_QSTR_Font_A32), MP_ROM_INT(Font_A32) }, 1588 | { MP_ROM_QSTR(MP_QSTR_Font_R32), MP_ROM_INT(Font_R32) } 1589 | 1590 | }; 1591 | 1592 | STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table); 1593 | 1594 | const mp_obj_module_t mp_module_framebuf = { 1595 | .base = { &mp_type_module }, 1596 | .globals = (mp_obj_dict_t *)&framebuf_module_globals, 1597 | }; 1598 | 1599 | MP_REGISTER_MODULE(MP_QSTR_framebuf, mp_module_framebuf); 1600 | #endif 1601 | 1602 | #endif // MICROPY_PY_FRAMEBUF 1603 | -------------------------------------------------------------------------------- /modframebuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2016 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "py/runtime.h" 32 | #include "py/binary.h" 33 | #include "py/stream.h" 34 | #include "py/reader.h" 35 | #include "extmod/vfs.h" 36 | 37 | #include "lib/oofatfs/ff.h" 38 | 39 | #if MICROPY_PY_FRAMEBUF 40 | 41 | #include "extmod/font_asc.h" 42 | 43 | 44 | typedef struct _font_set_t{ 45 | uint8_t f_style; 46 | uint8_t rotate; //xuanzhuan 47 | uint8_t scale; //fangda 16jinzhi ,gaowei hengxiang diweizongxiang 48 | uint8_t inverse; //fanbai 49 | uint16_t bg_col; 50 | uint8_t transparent; 51 | }font_set_t; 52 | 53 | typedef struct _font_inf_t{ 54 | uint32_t Font_Type; //1 GB2312,2 GB18030,3 small font ,0 None font 55 | uint32_t Base_Addr12; //xuanzhuan 0,12dot font no exist 56 | uint32_t Base_Addr16; //xuanzhuan 0,16dot font no exist 57 | uint32_t Base_Addr24; //xuanzhuan 0,24dot font no exist 58 | uint32_t Base_Addr32; //xuanzhuan 0,32dot font no exist 59 | }font_inf_t; 60 | 61 | typedef struct _mp_obj_framebuf_t { 62 | mp_obj_base_t base; 63 | mp_obj_t buf_obj; // need to store this to prevent GC from reclaiming buf 64 | mp_obj_t font_file; 65 | font_set_t font_set; 66 | font_inf_t font_inf; 67 | void *buf; 68 | uint16_t width, height, stride; 69 | uint8_t format; 70 | } mp_obj_framebuf_t; 71 | 72 | #if !MICROPY_ENABLE_DYNRUNTIME 73 | STATIC const mp_obj_type_t mp_type_framebuf; 74 | #endif 75 | 76 | typedef void (*setpixel_t)(const mp_obj_framebuf_t *, int, int, uint32_t); 77 | typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t *, int, int); 78 | 79 | typedef struct _mp_framebuf_p_t { 80 | setpixel_t setpixel; 81 | getpixel_t getpixel; 82 | } mp_framebuf_p_t; 83 | 84 | // constants for formats 85 | // 86 | #define FRAMEBUF_MON_VLSB (0X00) 87 | #define FRAMEBUF_MON_VMSB (0X01) 88 | #define FRAMEBUF_MON_HLSB (0X02) 89 | #define FRAMEBUF_MON_HMSB (0X03) 90 | 91 | #define FRAMEBUF_GS2_VLSB (0X20) 92 | #define FRAMEBUF_GS2_VMSB (0X21) 93 | #define FRAMEBUF_GS2_HLSB (0X22) 94 | #define FRAMEBUF_GS2_HMSB (0X23) 95 | 96 | #define FRAMEBUF_GS4_VLSB (0X40) 97 | #define FRAMEBUF_GS4_VMSB (0X41) 98 | #define FRAMEBUF_GS4_HLSB (0X42) 99 | #define FRAMEBUF_GS4_HMSB (0X43) 100 | 101 | #define FRAMEBUF_GS8_V (0X60) 102 | #define FRAMEBUF_GS8_H (0X62) 103 | 104 | #define FRAMEBUF_RGB565 (0X80) 105 | #define FRAMEBUF_RGB565SW (0X81) 106 | #define FRAMEBUF_RGB888 (0X82) 107 | #define FRAMEBUF_RGB8888 (0X83) 108 | 109 | #define FRAMEBUF_ST7302 (0XA0) 110 | 111 | #define FRAMEBUF_MX (0X04) 112 | #define FRAMEBUF_MY (0X08) 113 | #define FRAMEBUF_MV (0X10) 114 | 115 | 116 | // constants for formats 117 | #define Font_S12 (0x11) 118 | #define Font_C12 (0x21) 119 | #define Font_A12 (0x31) 120 | #define Font_R12 (0x41) 121 | 122 | #define Font_S16 (0x12) 123 | #define Font_C16 (0x22) 124 | #define Font_A16 (0x32) 125 | #define Font_R16 (0x42) 126 | 127 | #define Font_S24 (0x13) 128 | #define Font_C24 (0x23) 129 | #define Font_A24 (0x33) 130 | #define Font_R24 (0x43) 131 | 132 | #define Font_S32 (0x14) 133 | #define Font_C32 (0x24) 134 | #define Font_A32 (0x34) 135 | #define Font_R32 (0x44) 136 | 137 | 138 | 139 | mp_uint_t f_seek(mp_obj_t filename, mp_uint_t offset,mp_uint_t whence) { 140 | struct mp_stream_seek_t seek_s; 141 | 142 | seek_s.offset = offset; 143 | seek_s.whence = whence; 144 | 145 | // In POSIX, it's error to seek before end of stream, we enforce it here. 146 | if (seek_s.whence == SEEK_SET && seek_s.offset < 0) { 147 | mp_raise_OSError(MP_EINVAL); 148 | } 149 | 150 | const mp_stream_p_t *stream_p = mp_get_stream(filename); 151 | int error; 152 | mp_uint_t res = stream_p->ioctl(filename, MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error); 153 | if (res == MP_STREAM_ERROR) { 154 | mp_raise_OSError(error); 155 | } 156 | 157 | return seek_s.offset; 158 | } 159 | 160 | STATIC mp_obj_t framebuf_font_load(mp_obj_t self_in, mp_obj_t name_in) { 161 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 162 | const char *filename = mp_obj_str_get_str(name_in); 163 | //mp_printf(&mp_plat_print,"%s\n\r",filename); 164 | mp_obj_t f_args[2] = { 165 | mp_obj_new_str(filename, strlen(filename)), 166 | MP_OBJ_NEW_QSTR(MP_QSTR_rb), 167 | }; 168 | self->font_file = mp_vfs_open(MP_ARRAY_SIZE(f_args), &f_args[0], (mp_map_t *)&mp_const_empty_map); 169 | //尝试添加判断 170 | f_seek(self->font_file, 32,SEEK_SET); 171 | int errcode; 172 | int len=mp_stream_rw(self->font_file ,&self->font_inf, 20, &errcode, MP_STREAM_RW_READ); 173 | if (errcode != 0 && len!=20) { 174 | mp_raise_OSError(errcode); 175 | memset(&self->font_inf,0,20); 176 | self->font_file=NULL; 177 | mp_printf(&mp_plat_print,"Read %s error!\n\r",filename); 178 | } 179 | return mp_const_none; 180 | } 181 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_font_load_obj, framebuf_font_load); 182 | 183 | STATIC mp_obj_t framebuf_font_free(mp_obj_t self_in) { 184 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 185 | if (self->font_file != NULL){ 186 | mp_stream_close(self->font_file); 187 | mp_printf(&mp_plat_print,"font file close \n\r"); 188 | self->font_file=NULL; 189 | } 190 | return mp_const_none; 191 | } 192 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(framebuf_font_free_obj, framebuf_font_free); 193 | 194 | // Functions for MHLSB and MHMSB 195 | 196 | STATIC mp_obj_t framebuf_font_set(size_t n_args, const mp_obj_t *args) { 197 | (void)n_args; 198 | uint8_t prompt=0; 199 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 200 | mp_int_t style = mp_obj_get_int(args[1]); 201 | mp_int_t rotate =0; 202 | if (n_args > 2) { 203 | rotate = mp_obj_get_int(args[2]); 204 | } 205 | mp_int_t scale=1; 206 | if (n_args > 3) { 207 | scale = mp_obj_get_int(args[3]); 208 | } 209 | mp_int_t inverse =0; 210 | if (n_args > 4) { 211 | inverse = mp_obj_get_int(args[4]); 212 | } 213 | mp_int_t bg_col =0; 214 | if (n_args > 5) { 215 | bg_col = mp_obj_get_int(args[5]); 216 | self->font_set.transparent=0; 217 | }else{ 218 | self->font_set.transparent=1; 219 | } 220 | if ((style&0x0f)>4) { 221 | style=0x11; 222 | prompt=1; 223 | } 224 | self->font_set.f_style=style; 225 | 226 | if (scale==0){ 227 | scale=1; 228 | prompt=1; 229 | } 230 | if (scale>4){ 231 | scale=4; 232 | prompt=1; 233 | } 234 | self->font_set.scale=scale; 235 | 236 | if (rotate>3){ 237 | rotate=3; 238 | prompt=1; 239 | } 240 | self->font_set.rotate=rotate; 241 | if (inverse>1){ 242 | inverse=1; 243 | prompt=1; 244 | } 245 | self->font_set.inverse=inverse; 246 | self->font_set.bg_col=bg_col; 247 | if (prompt==1){ 248 | mp_printf(&mp_plat_print,"style=%d,rotate=%d,scale=%d,inverse=%d,bg_col=%d\n\r",self->font_set.f_style,self->font_set.rotate,self->font_set.scale,self->font_set.inverse,self->font_set.bg_col); 249 | } 250 | return mp_const_none; 251 | } 252 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_font_set_obj, 2, 6, framebuf_font_set); 253 | // Functions for st7302 format 254 | 255 | STATIC void st7302_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 256 | //bit0设置位顺序,0低位在前,bit1设置排列方式,0为垂直方式方式 257 | int index; 258 | int offset; 259 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 260 | index = ((y >> 1) * fb->stride + x) >> 2; 261 | offset = 7 - (((x<<1) & 0x06) + (y & 0x01)); 262 | }else{ 263 | index = ((x >> 1) * fb->stride + y) >> 2; 264 | offset = 7 - (((y<<1) & 0x06) + (x & 0x01)); 265 | } 266 | ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset); 267 | } 268 | 269 | STATIC uint32_t st7302_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 270 | int index; 271 | int offset; 272 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 273 | index = ((y >> 1) * fb->stride + x) >> 2; 274 | offset = 7 - (((x<<1) & 0x06) + (y & 0x01)); 275 | }else{ 276 | index = ((x >> 1) * fb->stride + y) >> 2; 277 | offset = 7 - (((y<<1) & 0x06) + (x & 0x01)); 278 | } 279 | return (((uint8_t *)fb->buf)[index] >> (offset)) & 0x01; 280 | } 281 | 282 | // Functions for mon format 283 | 284 | STATIC void mon_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 285 | //bit0设置位顺序,0低位在前,bit1设置排列方式,0为垂直方式方式 286 | int index; 287 | int offset; 288 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 289 | if ((fb->format & 0x02) == 0x00){ 290 | index = x + (y >> 3) * fb->stride; 291 | offset = (fb->format & 0x01) == 0 ? y & 0x07 : 7 - (y & 0x07); 292 | }else{ 293 | index = (x + y * fb->stride) >> 3; 294 | offset = (fb->format & 0x01) == 0 ? x & 0x07 : 7 - (x & 0x07); 295 | } 296 | }else{ 297 | if ((fb->format & 0x02) == 0x00){ 298 | index = (y + x * fb->stride) >> 3; 299 | offset = (fb->format & 0x01) == 0 ? y & 0x07 : 7 - (y & 0x07); 300 | }else{ 301 | index = y + (x >> 3) * fb->stride; 302 | offset = (fb->format & 0x01) == 0 ? x & 0x07 : 7 - (x & 0x07); 303 | } 304 | } 305 | ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset); 306 | } 307 | 308 | STATIC uint32_t mon_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 309 | int index; 310 | int offset; 311 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 312 | if ((fb->format & 0x02) == 0x00){ 313 | index = x + (y >> 3) * fb->stride; 314 | offset = (fb->format & 0x01) == 0 ? y & 0x07 : 7 - (y & 0x07); 315 | }else{ 316 | index = (x + y * fb->stride) >> 3; 317 | offset = (fb->format & 0x01) == 0 ? x & 0x07 : 7 - (x & 0x07); 318 | } 319 | }else{ 320 | if ((fb->format & 0x02) == 0x00){ 321 | index = (y + x * fb->stride) >> 3; 322 | offset = (fb->format & 0x01) == 0 ? y & 0x07 : 7 - (y & 0x07); 323 | }else{ 324 | index = y + (x >> 3) * fb->stride; 325 | offset = (fb->format & 0x01) == 0 ? x & 0x07 : 7 - (x & 0x07); 326 | } 327 | } 328 | return (((uint8_t *)fb->buf)[index] >> (offset)) & 0x01; 329 | } 330 | 331 | // Functions for GS2 format 332 | 333 | STATIC void gs2_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 334 | //bit0设置位顺序,0低位在前,bit1设置排列方式,0为垂直方式 335 | int index; 336 | int offset; 337 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 338 | if ((fb->format & 0x02) == 0x00){ 339 | index = x + (y >> 2) * fb->stride; 340 | offset = (fb->format & 0x01) == 0 ? y & 0x03 : 3 - (y & 0x03); 341 | }else{ 342 | index = (x + y * fb->stride) >> 2; 343 | offset = (fb->format & 0x01) == 0 ? x & 0x03 : 3 - (x & 0x03); 344 | } 345 | }else{ 346 | if ((fb->format & 0x02) == 0x00){ 347 | index = (y + x * fb->stride) >> 2; 348 | offset = (fb->format & 0x01) == 0 ? y & 0x03 : 3 - (y & 0x03); 349 | }else{ 350 | index = y + (x >> 2) * fb->stride; 351 | offset = (fb->format & 0x01) == 0 ? x & 0x03 : 3 - (x & 0x03); 352 | } 353 | } 354 | ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x03 << (offset*2))) | ((col &0x03) << (offset*2)); 355 | } 356 | 357 | STATIC uint32_t gs2_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 358 | int index; 359 | int offset; 360 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 361 | if ((fb->format & 0x02) == 0x00){ 362 | index = x + (y >> 2) * fb->stride; 363 | offset = (fb->format & 0x01) == 0 ? y & 0x03 : 3 - (y & 0x03); 364 | }else{ 365 | index = (x + y * fb->stride) >> 2; 366 | offset = (fb->format & 0x01) == 0 ? x & 0x03 : 3 - (x & 0x03); 367 | } 368 | }else{ 369 | if ((fb->format & 0x02) == 0x00){ 370 | index = (y + x * fb->stride) >> 2; 371 | offset = (fb->format & 0x01) == 0 ? y & 0x03 : 3 - (y & 0x03); 372 | }else{ 373 | index = y + (x >> 2) * fb->stride; 374 | offset = (fb->format & 0x01) == 0 ? x & 0x03 : 3 - (x & 0x03); 375 | } 376 | } 377 | return (((uint8_t *)fb->buf)[index] >> (offset*2)) & 0x03; 378 | } 379 | 380 | // Functions for GS4 format 381 | 382 | STATIC void gs4_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 383 | //bit0设置位顺序,0低位在前,bit1设置排列方式,0为垂直方式 384 | int index; 385 | int offset; 386 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 387 | if ((fb->format & 0x02) == 0x00){ 388 | index = x + (y >> 1) * fb->stride; 389 | offset = (fb->format & 0x01) == 0 ? y & 0x01 : 1 - (y & 0x01); 390 | }else{ 391 | index = (x + y * fb->stride) >> 1; 392 | offset = (fb->format & 0x01) == 0 ? x & 0x01 : 1 - (x & 0x01); 393 | } 394 | }else{ 395 | if ((fb->format & 0x02) == 0x00){ 396 | index = (y + x * fb->stride) >> 1; 397 | offset = (fb->format & 0x01) == 0 ? y & 0x01 : 1 - (y & 0x01); 398 | }else{ 399 | index = y + (x >> 1) * fb->stride; 400 | offset = (fb->format & 0x01) == 0 ? x & 0x01 : 1 - (x & 0x01); 401 | } 402 | } 403 | ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x0f << (offset*4))) | ((col &0x0f) << (offset*4)); 404 | } 405 | 406 | STATIC uint32_t gs4_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 407 | int index; 408 | int offset; 409 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 410 | if ((fb->format & 0x02) == 0x00){ 411 | index = x + (y >> 1) * fb->stride; 412 | offset = (fb->format & 0x01) == 0 ? y & 0x01 : 1 - (y & 0x01); 413 | }else{ 414 | index = (x + y * fb->stride) >> 1; 415 | offset = (fb->format & 0x01) == 0 ? x & 0x01 : 1 - (x & 0x01); 416 | } 417 | }else{ 418 | if ((fb->format & 0x02) == 0x00){ 419 | index = (y + x * fb->stride) >> 1; 420 | offset = (fb->format & 0x01) == 0 ? y & 0x01 : 1 - (y & 0x01); 421 | }else{ 422 | index = y + (x >> 1) * fb->stride; 423 | offset = (fb->format & 0x01) == 0 ? x & 0x01 : 1 - (x & 0x01); 424 | } 425 | } 426 | return (((uint8_t *)fb->buf)[index] >> (offset*4)) & 0x0f; 427 | } 428 | 429 | // Functions for GS8 format 430 | 431 | STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 432 | int index; 433 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 434 | if ((fb->format & 0x02) == 0){ 435 | index = y * fb->stride + x; 436 | }else{ 437 | index = x * fb->stride + y; 438 | } 439 | }else{ 440 | if ((fb->format & 0x02) == 0){ 441 | index = y * fb->stride + x; 442 | }else{ 443 | index = x * fb->stride + y; 444 | } 445 | } 446 | ((uint8_t *)fb->buf)[index] = col & 0xff; 447 | } 448 | 449 | STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 450 | int index; 451 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 452 | if ((fb->format & 0x02) == 0){ 453 | index = y * fb->stride + x; 454 | }else{ 455 | index = x * fb->stride + y; 456 | } 457 | }else{ 458 | if ((fb->format & 0x02) == 0){ 459 | index = y * fb->stride + x; 460 | }else{ 461 | index = x * fb->stride + y; 462 | } 463 | } 464 | return ((uint8_t *)fb->buf)[index]; 465 | } 466 | 467 | // Functions for RGB format 468 | 469 | STATIC void rgb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 470 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 471 | switch (fb->format&0x1F){ 472 | case 0: 473 | ((uint16_t *)fb->buf)[x + y * fb->stride] = col; 474 | break; 475 | case 1: 476 | ((uint8_t *)fb->buf)[(x + y * fb->stride)*2] = (col>>8)&0xff; 477 | ((uint8_t *)fb->buf)[(x + y * fb->stride)*2+1] = col&0xff; 478 | break; 479 | case 2: 480 | ((uint8_t *)fb->buf)[(x + y * fb->stride)*3] = (col>>16)&0xff; 481 | ((uint8_t *)fb->buf)[(x + y * fb->stride)*3+1] = (col>> 8)&0xff; 482 | ((uint8_t *)fb->buf)[(x + y * fb->stride)*3+2] = col&0xff; 483 | break; 484 | case 3: 485 | ((uint32_t *)fb->buf)[x + y * fb->stride] = col; 486 | break; 487 | } 488 | }else{ 489 | switch (fb->format&0x1F){ 490 | case 0: 491 | ((uint16_t *)fb->buf)[y + x * fb->stride] = col; 492 | break; 493 | case 1: 494 | ((uint8_t *)fb->buf)[(y + x * fb->stride)*2] = (col>>8)&0xff; 495 | ((uint8_t *)fb->buf)[(y + x * fb->stride)*2+1] = col&0xff; 496 | break; 497 | case 2: 498 | ((uint8_t *)fb->buf)[(y + x * fb->stride)*3] = (col>>16)&0xff; 499 | ((uint8_t *)fb->buf)[(y + x * fb->stride)*3+1] = (col>> 8)&0xff; 500 | ((uint8_t *)fb->buf)[(y + x * fb->stride)*3+2] = col&0xff; 501 | break; 502 | case 3: 503 | ((uint32_t *)fb->buf)[y + x * fb->stride] = col; 504 | break; 505 | } 506 | 507 | } 508 | } 509 | 510 | STATIC uint32_t rgb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 511 | if ((fb->format & FRAMEBUF_MV) == 0x00){ 512 | switch (fb->format&0x1F){ 513 | case 0: 514 | return ((uint16_t *)fb->buf)[x + y * fb->stride]; 515 | break; 516 | case 1: 517 | return ((((uint8_t *)fb->buf)[(x + y * fb->stride)*2]<<8)|((uint8_t *)fb->buf)[(x + y * fb->stride)*2+1] ); 518 | break; 519 | case 2: 520 | return ((((uint8_t *)fb->buf)[(x + y * fb->stride)*3]<<16)|(((uint8_t *)fb->buf)[(x + y * fb->stride)*3+1]<<8) 521 | ||((uint8_t *)fb->buf)[(x + y * fb->stride)*3+2]); 522 | break; 523 | case 3: 524 | return ((uint32_t *)fb->buf)[x + y * fb->stride]; 525 | break; 526 | } 527 | }else{ 528 | switch (fb->format&0x1F){ 529 | case 0: 530 | return ((uint16_t *)fb->buf)[y + x * fb->stride]; 531 | break; 532 | case 1: 533 | return ((((uint8_t *)fb->buf)[(y + x * fb->stride)*2]<<8)|((uint8_t *)fb->buf)[(y + x * fb->stride)*2+1] ); 534 | break; 535 | case 2: 536 | return ((((uint8_t *)fb->buf)[(y + x * fb->stride)*3]<<16)|(((uint8_t *)fb->buf)[(y + x * fb->stride)*3+1]<<8) 537 | ||((uint8_t *)fb->buf)[(y + x * fb->stride)*3+2]); 538 | break; 539 | case 3: 540 | return ((uint32_t *)fb->buf)[y + x * fb->stride]; 541 | break; 542 | } 543 | } 544 | return 0; 545 | } 546 | 547 | 548 | STATIC mp_framebuf_p_t formats[] = { 549 | [FRAMEBUF_MON_VLSB&0xE0] = {mon_setpixel, mon_getpixel}, 550 | [FRAMEBUF_GS2_HMSB&0xE0] = {gs2_setpixel, gs2_getpixel}, 551 | [FRAMEBUF_GS4_HMSB&0xE0] = {gs4_setpixel, gs4_getpixel}, 552 | [FRAMEBUF_GS8_H&0xE0] = {gs8_setpixel, gs8_getpixel}, 553 | [FRAMEBUF_RGB565&0xE0] = {rgb_setpixel, rgb_getpixel}, 554 | [FRAMEBUF_ST7302&0xE0] = {st7302_setpixel, st7302_getpixel}, 555 | 556 | }; 557 | 558 | static inline void setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { 559 | if (0 <= x && x < fb->width && 0 <= y && y < fb->height){ 560 | if ((fb->format&FRAMEBUF_MX)==FRAMEBUF_MX) 561 | x=fb->width-x-1; 562 | if ((fb->format&FRAMEBUF_MY)==FRAMEBUF_MY) 563 | y=fb->height-y-1; 564 | if (x>=0 && xwidth && y>=0 && yheight) 565 | formats[fb->format&0xE0].setpixel(fb, x, y, col); 566 | } 567 | } 568 | 569 | STATIC void setpixel_checked(const mp_obj_framebuf_t *fb, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) { 570 | if (mask && 0 <= x && x < fb->width && 0 <= y && y < fb->height) { 571 | setpixel(fb, x, y, col); 572 | } 573 | } 574 | 575 | static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, int x, int y) { 576 | if (0 <= x && x < fb->width && 0 <= y && y < fb->height){ 577 | if ((fb->format&FRAMEBUF_MX)==FRAMEBUF_MX) 578 | x=fb->width-x-1; 579 | if ((fb->format&FRAMEBUF_MY)==FRAMEBUF_MY) 580 | y=fb->height-y-1; 581 | return formats[fb->format&0xE0].getpixel(fb, x, y); 582 | }else{ 583 | return 0; 584 | } 585 | 586 | } 587 | 588 | STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { 589 | if (h < 1 || w < 1 || x + w <= 0 || y + h <= 0 || y >= fb->height || x >= fb->width) { 590 | // No operation needed. 591 | return; 592 | } 593 | for (int xx = x; xx < x + w; xx++) { 594 | for (int yy = y; yy < y + h; yy++) { 595 | setpixel(fb, xx, yy, col); 596 | } 597 | } 598 | } 599 | 600 | STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { 601 | mp_arg_check_num(n_args, n_kw, 4, 5, false); 602 | 603 | mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t); 604 | o->base.type = type; 605 | o->buf_obj = args[0]; 606 | 607 | mp_buffer_info_t bufinfo; 608 | mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE); 609 | o->buf = bufinfo.buf; 610 | 611 | o->width = mp_obj_get_int(args[1]); 612 | o->height = mp_obj_get_int(args[2]); 613 | o->format = mp_obj_get_int(args[3]); 614 | if (n_args > 4) { 615 | o->stride = mp_obj_get_int(args[4]); 616 | } else { 617 | if ((o->format & FRAMEBUF_MV) == 0x00){ 618 | o->stride = o->width; 619 | }else{ 620 | o->stride = o->height; 621 | } 622 | } 623 | //font style seting 624 | o->font_set.f_style=0x11; 625 | o->font_set.scale=1; 626 | o->font_set.rotate=0; 627 | o->font_set.inverse=0; 628 | o->font_set.transparent=1; 629 | o->font_set.bg_col=0; 630 | o->font_file=NULL; 631 | o->font_inf.Font_Type=0; 632 | o->font_inf.Base_Addr12=0; //xuanzhuan 0,12dot font no exist 633 | o->font_inf.Base_Addr16=0; //xuanzhuan 0,16dot font no exist 634 | o->font_inf.Base_Addr24=0; //xuanzhuan 0,24dot font no exist 635 | o->font_inf.Base_Addr32=0; //xuanzhuan 0,32dot font no exist 636 | //确认垂直方式也需要处理stride,另外定义buffer时也需要处理 637 | switch (o->format&0xE0) { 638 | case FRAMEBUF_ST7302: 639 | o->stride = (o->stride + 11) / 12 * 12; 640 | break; 641 | case FRAMEBUF_GS8_H: 642 | case FRAMEBUF_GS8_V: 643 | case FRAMEBUF_RGB565: 644 | case FRAMEBUF_RGB565SW: 645 | case FRAMEBUF_RGB888: 646 | case FRAMEBUF_RGB8888: 647 | break; 648 | case FRAMEBUF_MON_VLSB: 649 | case FRAMEBUF_MON_VMSB: 650 | case FRAMEBUF_MON_HLSB: 651 | case FRAMEBUF_MON_HMSB: 652 | o->stride = (o->stride + 7) & ~7; 653 | break; 654 | case FRAMEBUF_GS2_VLSB: 655 | case FRAMEBUF_GS2_VMSB: 656 | case FRAMEBUF_GS2_HLSB: 657 | case FRAMEBUF_GS2_HMSB: 658 | o->stride = (o->stride + 3) & ~3; 659 | break; 660 | case FRAMEBUF_GS4_VLSB: 661 | case FRAMEBUF_GS4_VMSB: 662 | case FRAMEBUF_GS4_HLSB: 663 | case FRAMEBUF_GS4_HMSB: 664 | o->stride = (o->stride + 1) & ~1; 665 | break; 666 | default: 667 | mp_raise_ValueError(MP_ERROR_TEXT("invalid format")); 668 | } 669 | //mp_printf(&mp_plat_print,"w=%d,h=%d,f=%d,s=%d\n\r",o->width,o->height,o->format,o->stride); 670 | return MP_OBJ_FROM_PTR(o); 671 | } 672 | 673 | STATIC void framebuf_args(const mp_obj_t *args_in, mp_int_t *args_out, int n) { 674 | for (int i = 0; i < n; ++i) { 675 | args_out[i] = mp_obj_get_int(args_in[i + 1]); 676 | } 677 | } 678 | 679 | STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { 680 | (void)flags; 681 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 682 | bufinfo->buf = self->buf; 683 | u_int8_t size=1; 684 | if ((self->format == FRAMEBUF_RGB565)||(self->format == FRAMEBUF_RGB565)){ 685 | size=2; 686 | }else if(self->format == FRAMEBUF_RGB888){ 687 | size=3; 688 | }else if(self->format == FRAMEBUF_RGB8888){ 689 | size=4; 690 | } 691 | bufinfo->len = self->stride * self->height * size; 692 | bufinfo->typecode = 'B'; // view framebuf as bytes 693 | return 0; 694 | } 695 | 696 | STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) { 697 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 698 | mp_int_t col = mp_obj_get_int(col_in); 699 | fill_rect(self, 0, 0, self->width, self->height, col); 700 | return mp_const_none; 701 | } 702 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill); 703 | 704 | STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args_in) { 705 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); 706 | mp_int_t args[5]; // x, y, w, h, col 707 | framebuf_args(args_in, args, 5); 708 | fill_rect(self, args[0], args[1], args[2], args[3], args[4]); 709 | return mp_const_none; 710 | } 711 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect); 712 | 713 | STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) { 714 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 715 | mp_int_t x = mp_obj_get_int(args[1]); 716 | mp_int_t y = mp_obj_get_int(args[2]); 717 | if (0 <= x && x < self->width && 0 <= y && y < self->height) { 718 | if (n_args == 3) { 719 | // get 720 | return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y)); 721 | } else { 722 | // set 723 | setpixel(self, x, y, mp_obj_get_int(args[3])); 724 | } 725 | } 726 | return mp_const_none; 727 | } 728 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel); 729 | 730 | STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args_in) { 731 | (void)n_args; 732 | 733 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); 734 | mp_int_t args[4]; // x, y, w, col 735 | framebuf_args(args_in, args, 4); 736 | 737 | fill_rect(self, args[0], args[1], args[2], 1, args[3]); 738 | 739 | return mp_const_none; 740 | } 741 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline); 742 | 743 | STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args_in) { 744 | (void)n_args; 745 | 746 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); 747 | mp_int_t args[4]; // x, y, h, col 748 | framebuf_args(args_in, args, 4); 749 | 750 | fill_rect(self, args[0], args[1], 1, args[2], args[3]); 751 | 752 | return mp_const_none; 753 | } 754 | 755 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline); 756 | 757 | STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args_in) { 758 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); 759 | mp_int_t args[5]; // x, y, w, h, col 760 | framebuf_args(args_in, args, 5); 761 | if (n_args > 6 && mp_obj_is_true(args_in[6])) { 762 | fill_rect(self, args[0], args[1], args[2], args[3], args[4]); 763 | } else { 764 | fill_rect(self, args[0], args[1], args[2], 1, args[4]); 765 | fill_rect(self, args[0], args[1] + args[3] - 1, args[2], 1, args[4]); 766 | fill_rect(self, args[0], args[1], 1, args[3], args[4]); 767 | fill_rect(self, args[0] + args[2] - 1, args[1], 1, args[3], args[4]); 768 | } 769 | return mp_const_none; 770 | } 771 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect); 772 | 773 | STATIC void line(const mp_obj_framebuf_t *fb, mp_int_t x1, mp_int_t y1, mp_int_t x2, mp_int_t y2, mp_int_t col) { 774 | mp_int_t dx = x2 - x1; 775 | mp_int_t sx; 776 | if (dx > 0) { 777 | sx = 1; 778 | } else { 779 | dx = -dx; 780 | sx = -1; 781 | } 782 | 783 | mp_int_t dy = y2 - y1; 784 | mp_int_t sy; 785 | if (dy > 0) { 786 | sy = 1; 787 | } else { 788 | dy = -dy; 789 | sy = -1; 790 | } 791 | 792 | bool steep; 793 | if (dy > dx) { 794 | mp_int_t temp; 795 | temp = x1; 796 | x1 = y1; 797 | y1 = temp; 798 | temp = dx; 799 | dx = dy; 800 | dy = temp; 801 | temp = sx; 802 | sx = sy; 803 | sy = temp; 804 | steep = true; 805 | } else { 806 | steep = false; 807 | } 808 | 809 | mp_int_t e = 2 * dy - dx; 810 | for (mp_int_t i = 0; i < dx; ++i) { 811 | if (steep) { 812 | if (0 <= y1 && y1 < fb->width && 0 <= x1 && x1 < fb->height) { 813 | setpixel(fb, y1, x1, col); 814 | } 815 | } else { 816 | if (0 <= x1 && x1 < fb->width && 0 <= y1 && y1 < fb->height) { 817 | setpixel(fb, x1, y1, col); 818 | } 819 | } 820 | while (e >= 0) { 821 | y1 += sy; 822 | e -= 2 * dx; 823 | } 824 | x1 += sx; 825 | e += 2 * dy; 826 | } 827 | 828 | if (0 <= x2 && x2 < fb->width && 0 <= y2 && y2 < fb->height) { 829 | setpixel(fb, x2, y2, col); 830 | } 831 | } 832 | 833 | STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) { 834 | (void)n_args; 835 | 836 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); 837 | mp_int_t args[5]; // x1, y1, x2, y2, col 838 | framebuf_args(args_in, args, 5); 839 | 840 | line(self, args[0], args[1], args[2], args[3], args[4]); 841 | 842 | return mp_const_none; 843 | } 844 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line); 845 | 846 | // Q2 Q1 847 | // Q3 Q4 848 | #define ELLIPSE_MASK_FILL (0x10) 849 | #define ELLIPSE_MASK_ALL (0x0f) 850 | #define ELLIPSE_MASK_Q1 (0x01) 851 | #define ELLIPSE_MASK_Q2 (0x02) 852 | #define ELLIPSE_MASK_Q3 (0x04) 853 | #define ELLIPSE_MASK_Q4 (0x08) 854 | 855 | STATIC void draw_ellipse_points(const mp_obj_framebuf_t *fb, mp_int_t cx, mp_int_t cy, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) { 856 | if (mask & ELLIPSE_MASK_FILL) { 857 | if (mask & ELLIPSE_MASK_Q1) { 858 | fill_rect(fb, cx, cy - y, x + 1, 1, col); 859 | } 860 | if (mask & ELLIPSE_MASK_Q2) { 861 | fill_rect(fb, cx - x, cy - y, x + 1, 1, col); 862 | } 863 | if (mask & ELLIPSE_MASK_Q3) { 864 | fill_rect(fb, cx - x, cy + y, x + 1, 1, col); 865 | } 866 | if (mask & ELLIPSE_MASK_Q4) { 867 | fill_rect(fb, cx, cy + y, x + 1, 1, col); 868 | } 869 | } else { 870 | setpixel_checked(fb, cx + x, cy - y, col, mask & ELLIPSE_MASK_Q1); 871 | setpixel_checked(fb, cx - x, cy - y, col, mask & ELLIPSE_MASK_Q2); 872 | setpixel_checked(fb, cx - x, cy + y, col, mask & ELLIPSE_MASK_Q3); 873 | setpixel_checked(fb, cx + x, cy + y, col, mask & ELLIPSE_MASK_Q4); 874 | } 875 | } 876 | 877 | STATIC mp_obj_t framebuf_ellipse(size_t n_args, const mp_obj_t *args_in) { 878 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); 879 | mp_int_t args[5]; 880 | framebuf_args(args_in, args, 5); // cx, cy, xradius, yradius, col 881 | mp_int_t mask = (n_args > 6 && mp_obj_is_true(args_in[6])) ? ELLIPSE_MASK_FILL : 0; 882 | if (n_args > 7) { 883 | mask |= mp_obj_get_int(args_in[7]) & ELLIPSE_MASK_ALL; 884 | } else { 885 | mask |= ELLIPSE_MASK_ALL; 886 | } 887 | mp_int_t two_asquare = 2 * args[2] * args[2]; 888 | mp_int_t two_bsquare = 2 * args[3] * args[3]; 889 | mp_int_t x = args[2]; 890 | mp_int_t y = 0; 891 | mp_int_t xchange = args[3] * args[3] * (1 - 2 * args[2]); 892 | mp_int_t ychange = args[2] * args[2]; 893 | mp_int_t ellipse_error = 0; 894 | mp_int_t stoppingx = two_bsquare * args[2]; 895 | mp_int_t stoppingy = 0; 896 | while (stoppingx >= stoppingy) { // 1st set of points, y' > -1 897 | draw_ellipse_points(self, args[0], args[1], x, y, args[4], mask); 898 | y += 1; 899 | stoppingy += two_asquare; 900 | ellipse_error += ychange; 901 | ychange += two_asquare; 902 | if ((2 * ellipse_error + xchange) > 0) { 903 | x -= 1; 904 | stoppingx -= two_bsquare; 905 | ellipse_error += xchange; 906 | xchange += two_bsquare; 907 | } 908 | } 909 | // 1st point set is done start the 2nd set of points 910 | x = 0; 911 | y = args[3]; 912 | xchange = args[3] * args[3]; 913 | ychange = args[2] * args[2] * (1 - 2 * args[3]); 914 | ellipse_error = 0; 915 | stoppingx = 0; 916 | stoppingy = two_asquare * args[3]; 917 | while (stoppingx <= stoppingy) { // 2nd set of points, y' < -1 918 | draw_ellipse_points(self, args[0], args[1], x, y, args[4], mask); 919 | x += 1; 920 | stoppingx += two_bsquare; 921 | ellipse_error += xchange; 922 | xchange += two_bsquare; 923 | if ((2 * ellipse_error + ychange) > 0) { 924 | y -= 1; 925 | stoppingy -= two_asquare; 926 | ellipse_error += ychange; 927 | ychange += two_asquare; 928 | } 929 | } 930 | return mp_const_none; 931 | } 932 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_ellipse_obj, 6, 8, framebuf_ellipse); 933 | 934 | #if MICROPY_PY_ARRAY && !MICROPY_ENABLE_DYNRUNTIME 935 | // TODO: poly needs mp_binary_get_size & mp_binary_get_val_array which aren't 936 | // available in dynruntime.h yet. 937 | 938 | STATIC mp_int_t poly_int(mp_buffer_info_t *bufinfo, size_t index) { 939 | return mp_obj_get_int(mp_binary_get_val_array(bufinfo->typecode, bufinfo->buf, index)); 940 | } 941 | 942 | STATIC mp_obj_t framebuf_poly(size_t n_args, const mp_obj_t *args_in) { 943 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]); 944 | 945 | mp_int_t x = mp_obj_get_int(args_in[1]); 946 | mp_int_t y = mp_obj_get_int(args_in[2]); 947 | 948 | mp_buffer_info_t bufinfo; 949 | mp_get_buffer_raise(args_in[3], &bufinfo, MP_BUFFER_READ); 950 | // If an odd number of values was given, this rounds down to multiple of two. 951 | int n_poly = bufinfo.len / (mp_binary_get_size('@', bufinfo.typecode, NULL) * 2); 952 | 953 | if (n_poly == 0) { 954 | return mp_const_none; 955 | } 956 | 957 | mp_int_t col = mp_obj_get_int(args_in[4]); 958 | bool fill = n_args > 5 && mp_obj_is_true(args_in[5]); 959 | 960 | if (fill) { 961 | // This implements an integer version of http://alienryderflex.com/polygon_fill/ 962 | 963 | // The idea is for each scan line, compute the sorted list of x 964 | // coordinates where the scan line intersects the polygon edges, 965 | // then fill between each resulting pair. 966 | 967 | // Restrict just to the scan lines that include the vertical extent of 968 | // this polygon. 969 | mp_int_t y_min = INT_MAX, y_max = INT_MIN; 970 | for (int i = 0; i < n_poly; i++) { 971 | mp_int_t py = poly_int(&bufinfo, i * 2 + 1); 972 | y_min = MIN(y_min, py); 973 | y_max = MAX(y_max, py); 974 | } 975 | 976 | for (mp_int_t row = y_min; row <= y_max; row++) { 977 | // Each node is the x coordinate where an edge crosses this scan line. 978 | mp_int_t nodes[n_poly]; 979 | int n_nodes = 0; 980 | mp_int_t px1 = poly_int(&bufinfo, 0); 981 | mp_int_t py1 = poly_int(&bufinfo, 1); 982 | int i = n_poly * 2 - 1; 983 | do { 984 | mp_int_t py2 = poly_int(&bufinfo, i--); 985 | mp_int_t px2 = poly_int(&bufinfo, i--); 986 | 987 | // Don't include the bottom pixel of a given edge to avoid 988 | // duplicating the node with the start of the next edge. This 989 | // will miss some pixels on the boundary, and in particular 990 | // at a local minima or inflection point. 991 | if (py1 != py2 && ((py1 > row && py2 <= row) || (py1 <= row && py2 > row))) { 992 | mp_int_t node = (32 * px1 + 32 * (px2 - px1) * (row - py1) / (py2 - py1) + 16) / 32; 993 | nodes[n_nodes++] = node; 994 | } else if (row == MAX(py1, py2)) { 995 | // At local-minima, try and manually fill in the pixels that get missed above. 996 | if (py1 < py2) { 997 | setpixel_checked(self, x + px2, y + py2, col, 1); 998 | } else if (py2 < py1) { 999 | setpixel_checked(self, x + px1, y + py1, col, 1); 1000 | } else { 1001 | // Even though this is a hline and would be faster to 1002 | // use fill_rect, use line() because it handles x2 < 1003 | // x1. 1004 | line(self, x + px1, y + py1, x + px2, y + py2, col); 1005 | } 1006 | } 1007 | 1008 | px1 = px2; 1009 | py1 = py2; 1010 | } while (i >= 0); 1011 | 1012 | if (!n_nodes) { 1013 | continue; 1014 | } 1015 | 1016 | // Sort the nodes left-to-right (bubble-sort for code size). 1017 | i = 0; 1018 | while (i < n_nodes - 1) { 1019 | if (nodes[i] > nodes[i + 1]) { 1020 | mp_int_t swap = nodes[i]; 1021 | nodes[i] = nodes[i + 1]; 1022 | nodes[i + 1] = swap; 1023 | if (i) { 1024 | i--; 1025 | } 1026 | } else { 1027 | i++; 1028 | } 1029 | } 1030 | 1031 | // Fill between each pair of nodes. 1032 | for (i = 0; i < n_nodes; i += 2) { 1033 | fill_rect(self, x + nodes[i], y + row, (nodes[i + 1] - nodes[i]) + 1, 1, col); 1034 | } 1035 | } 1036 | } else { 1037 | // Outline only. 1038 | mp_int_t px1 = poly_int(&bufinfo, 0); 1039 | mp_int_t py1 = poly_int(&bufinfo, 1); 1040 | int i = n_poly * 2 - 1; 1041 | do { 1042 | mp_int_t py2 = poly_int(&bufinfo, i--); 1043 | mp_int_t px2 = poly_int(&bufinfo, i--); 1044 | line(self, x + px1, y + py1, x + px2, y + py2, col); 1045 | px1 = px2; 1046 | py1 = py2; 1047 | } while (i >= 0); 1048 | } 1049 | 1050 | return mp_const_none; 1051 | } 1052 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_poly_obj, 5, 6, framebuf_poly); 1053 | #endif // MICROPY_PY_ARRAY && !MICROPY_ENABLE_DYNRUNTIME 1054 | 1055 | STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) { 1056 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 1057 | mp_obj_t source_in = mp_obj_cast_to_native_base(args[1], MP_OBJ_FROM_PTR(&mp_type_framebuf)); 1058 | if (source_in == MP_OBJ_NULL) { 1059 | mp_raise_TypeError(NULL); 1060 | } 1061 | mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(source_in); 1062 | 1063 | mp_int_t x = mp_obj_get_int(args[2]); 1064 | mp_int_t y = mp_obj_get_int(args[3]); 1065 | mp_int_t key = -1; 1066 | if (n_args > 4) { 1067 | key = mp_obj_get_int(args[4]); 1068 | } 1069 | mp_obj_framebuf_t *palette = NULL; 1070 | if (n_args > 5 && args[5] != mp_const_none) { 1071 | palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf))); 1072 | } 1073 | 1074 | if ( 1075 | (x >= self->width) || 1076 | (y >= self->height) || 1077 | (-x >= source->width) || 1078 | (-y >= source->height) 1079 | ) { 1080 | // Out of bounds, no-op. 1081 | return mp_const_none; 1082 | } 1083 | 1084 | // Clip. 1085 | int x0 = MAX(0, x); 1086 | int y0 = MAX(0, y); 1087 | int x1 = MAX(0, -x); 1088 | int y1 = MAX(0, -y); 1089 | int x0end = MIN(self->width, x + source->width); 1090 | int y0end = MIN(self->height, y + source->height); 1091 | 1092 | for (; y0 < y0end; ++y0) { 1093 | int cx1 = x1; 1094 | for (int cx0 = x0; cx0 < x0end; ++cx0) { 1095 | uint32_t col = getpixel(source, cx1, y1); 1096 | if (palette) { 1097 | col = getpixel(palette, col, 0); 1098 | } 1099 | if (col != (uint32_t)key) { 1100 | setpixel(self, cx0, y0, col); 1101 | } 1102 | ++cx1; 1103 | } 1104 | ++y1; 1105 | } 1106 | return mp_const_none; 1107 | } 1108 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 6, framebuf_blit); 1109 | 1110 | STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ystep_in) { 1111 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 1112 | mp_int_t xstep = mp_obj_get_int(xstep_in); 1113 | mp_int_t ystep = mp_obj_get_int(ystep_in); 1114 | int sx, y, xend, yend, dx, dy; 1115 | if (xstep < 0) { 1116 | sx = 0; 1117 | xend = self->width + xstep; 1118 | dx = 1; 1119 | } else { 1120 | sx = self->width - 1; 1121 | xend = xstep - 1; 1122 | dx = -1; 1123 | } 1124 | if (ystep < 0) { 1125 | y = 0; 1126 | yend = self->height + ystep; 1127 | dy = 1; 1128 | } else { 1129 | y = self->height - 1; 1130 | yend = ystep - 1; 1131 | dy = -1; 1132 | } 1133 | for (; y != yend; y += dy) { 1134 | for (int x = sx; x != xend; x += dx) { 1135 | setpixel(self, x, y, getpixel(self, x - xstep, y - ystep)); 1136 | } 1137 | } 1138 | return mp_const_none; 1139 | } 1140 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll); 1141 | 1142 | 1143 | uint32_t gethzk(mp_obj_framebuf_t *self,uint32_t unicode,uint8_t * chr_data,uint8_t * font_width,uint8_t * font_high,uint8_t * font_stride){ 1144 | uint8_t gbk[2]; 1145 | int len; 1146 | uint32_t font_index,code_index; 1147 | int errcode; 1148 | 1149 | switch(self->font_inf.Font_Type){ 1150 | case 0x0: 1151 | return 1; 1152 | break; 1153 | case 0x1: //gb2312 1154 | case 0x2: //gbk 1155 | //printf("unicode to gbk or gb2312\r\n"); 1156 | if ((unicode>=0x000080) && (unicode<=0x00047f)){ 1157 | code_index= unicode-0x80 ; 1158 | }else if ((unicode>=0x004e00) && (unicode<=0x009fa5)){ 1159 | code_index= unicode-0x4e00+0x0d00; 1160 | }else if ((unicode>=0x00ff00) && (unicode<=0x010000)){ 1161 | code_index= unicode-0xff00+0x0C00; 1162 | }else if ((unicode>=0x003000) && (unicode<=0x0030ff)){ 1163 | code_index= unicode-0x3000+0x0B00; 1164 | }else if ((unicode>=0x002000) && (unicode<=0x0026ff)){ 1165 | code_index= unicode-0x2000+0x0400; 1166 | }else{ 1167 | return 2; 1168 | } 1169 | f_seek(self->font_file, code_index *2+0x100,SEEK_SET); 1170 | len=mp_stream_rw(self->font_file ,gbk,2, &errcode, MP_STREAM_RW_READ); 1171 | if (len!=2 && errcode!=0) return 3; 1172 | if (self->font_inf.Font_Type==1){ 1173 | if (gbk[0]>=0xa1 && gbk[0]<=0xa9 && gbk[1]>=0xa1 && gbk[1]<=0xfe ){ 1174 | font_index=(gbk[0]-0xa1)*94+gbk[1]-0xa1; 1175 | } else if (gbk[0]>=0xb0 && gbk[0]<=0xf7 && gbk[1]>=0xa1 && gbk[1]<=0xfe ){ 1176 | font_index=(gbk[0]-0xb0)*94+gbk[1]-0xa1+846; 1177 | } else { return 4; } 1178 | }else if (self->font_inf.Font_Type==2){ 1179 | if(gbk[0]>=0x81 && gbk[0]<=0xfe && gbk[1]>=40 && gbk[1]<=0xfe){ 1180 | if(gbk[1]==0x7f) return 1; 1181 | if(gbk[1]>0x7f) gbk[1]-=1; 1182 | font_index=(gbk[0]-0x81)*190+gbk[1]-0x40; 1183 | }else{ return 4; } 1184 | }else{ return 4; } 1185 | //mp_printf(&mp_plat_print,"%8.8X",font_index); 1186 | switch(self->font_set.f_style&0x0f){ 1187 | case 0x1: 1188 | if (self->font_inf.Base_Addr12>0){ 1189 | * font_width=12; 1190 | * font_high=12; 1191 | * font_stride=2; 1192 | f_seek(self->font_file, font_index*24+self->font_inf.Base_Addr12,SEEK_SET); 1193 | int len=mp_stream_rw(self->font_file ,chr_data, 24 , &errcode, MP_STREAM_RW_READ); 1194 | if (len!=24 && errcode!=0) return 5; 1195 | }else { return 6; } 1196 | break; 1197 | case 0x2: 1198 | if (self->font_inf.Base_Addr16>0){ 1199 | * font_width=16; 1200 | * font_high=16; 1201 | * font_stride=2; 1202 | f_seek(self->font_file, font_index*32+self->font_inf.Base_Addr16,SEEK_SET); 1203 | int len=mp_stream_rw(self->font_file ,chr_data, 32 , &errcode, MP_STREAM_RW_READ); 1204 | if (len!=32 && errcode!=0) return 5; 1205 | }else { return 6; } 1206 | break; 1207 | case 0x3: 1208 | if (self->font_inf.Base_Addr24>0){ 1209 | * font_width=24; 1210 | * font_high=24; 1211 | * font_stride=3; 1212 | f_seek(self->font_file, font_index*72+self->font_inf.Base_Addr24,SEEK_SET); 1213 | int len=mp_stream_rw(self->font_file ,chr_data, 72 , &errcode, MP_STREAM_RW_READ); 1214 | if (len!=72 && errcode!=0) return 5; 1215 | }else { return 6; } 1216 | break; 1217 | case 0x4: 1218 | if (self->font_inf.Base_Addr32>0){ 1219 | * font_width=32; 1220 | * font_high=32; 1221 | * font_stride=4; 1222 | f_seek(self->font_file, font_index*128+self->font_inf.Base_Addr32,SEEK_SET); 1223 | int len=mp_stream_rw(self->font_file ,chr_data, 128 , &errcode, MP_STREAM_RW_READ); 1224 | if (len!=128 && errcode!=0) return 5; 1225 | }else { return 6; } 1226 | break; 1227 | default: 1228 | return 7; 1229 | break; 1230 | } 1231 | break; 1232 | case 0x3: //small font 1233 | switch(self->font_set.f_style&0x0f){ 1234 | case 0x1: 1235 | if (self->font_inf.Base_Addr12>0){ 1236 | * font_width=12; 1237 | * font_high=12; 1238 | * font_stride=2; 1239 | uint32_t font_count=0; 1240 | f_seek(self->font_file, 68,SEEK_SET); 1241 | int len=mp_stream_rw(self->font_file ,&font_count, 4 , &errcode, MP_STREAM_RW_READ); 1242 | if (len!=4 && errcode!=0) return 5; 1243 | if (font_count>1024 || font_count==0) return 5; 1244 | //mp_printf(&mp_plat_print,"%d--",font_count); 1245 | uint32_t font_index[font_count][2]; 1246 | f_seek(self->font_file, self->font_inf.Base_Addr12,SEEK_SET); 1247 | len=mp_stream_rw(self->font_file ,&font_index, font_count*8 , &errcode, MP_STREAM_RW_READ); 1248 | for(int find=0;findfont_file, font_index[find][1],SEEK_SET); 1251 | len=mp_stream_rw(self->font_file ,chr_data, 24 , &errcode, MP_STREAM_RW_READ); 1252 | if (len!=24 && errcode!=0) { return 5;} 1253 | else {return 0; } 1254 | } 1255 | } 1256 | return 6; 1257 | }else { return 6; } 1258 | break; 1259 | case 0x2: 1260 | if (self->font_inf.Base_Addr16>0){ 1261 | * font_width=16; 1262 | * font_high=16; 1263 | * font_stride=2; 1264 | uint32_t font_count=0; 1265 | f_seek(self->font_file, 72,SEEK_SET); 1266 | int len=mp_stream_rw(self->font_file ,&font_count, 4 , &errcode, MP_STREAM_RW_READ); 1267 | if (len!=4 && errcode!=0) return 5; 1268 | if (font_count>1024 || font_count==0) return 5; 1269 | uint32_t font_index[font_count][2]; 1270 | f_seek(self->font_file, self->font_inf.Base_Addr16,SEEK_SET); 1271 | len=mp_stream_rw(self->font_file ,&font_index, font_count*8 , &errcode, MP_STREAM_RW_READ); 1272 | for(int find=0;findfont_file, font_index[find][1],SEEK_SET); 1275 | len=mp_stream_rw(self->font_file ,chr_data, 32 , &errcode, MP_STREAM_RW_READ); 1276 | if (len!=32 && errcode!=0) {return 5; } 1277 | else {return 0; } 1278 | } 1279 | } 1280 | return 6; 1281 | }else { return 6; } 1282 | break; 1283 | case 0x3: 1284 | if (self->font_inf.Base_Addr24>0){ 1285 | * font_width=24; 1286 | * font_high=24; 1287 | * font_stride=3; 1288 | uint32_t font_count=0; 1289 | f_seek(self->font_file, 72,SEEK_SET); 1290 | int len=mp_stream_rw(self->font_file ,&font_count, 4 , &errcode, MP_STREAM_RW_READ); 1291 | if (len!=4 && errcode!=0) return 5; 1292 | if (font_count>1024 || font_count==0) return 5; 1293 | uint32_t font_index[font_count][2]; 1294 | f_seek(self->font_file, self->font_inf.Base_Addr24,SEEK_SET); 1295 | len=mp_stream_rw(self->font_file ,&font_index, font_count*8 , &errcode, MP_STREAM_RW_READ); 1296 | for(int find=0;findfont_file, font_index[find][1],SEEK_SET); 1299 | len=mp_stream_rw(self->font_file ,chr_data, 72, &errcode, MP_STREAM_RW_READ); 1300 | if (len!=72 && errcode!=0) {return 5; } 1301 | else {return 0; } 1302 | } 1303 | } 1304 | return 6; 1305 | }else { return 6; } 1306 | break; 1307 | case 0x4: 1308 | if (self->font_inf.Base_Addr32>0){ 1309 | * font_width=32; 1310 | * font_high=32; 1311 | * font_stride=4; 1312 | uint32_t font_count=0; 1313 | f_seek(self->font_file, 76,SEEK_SET); 1314 | int len=mp_stream_rw(self->font_file ,&font_count, 4 , &errcode, MP_STREAM_RW_READ); 1315 | if (len!=4 && errcode!=0) return 5; 1316 | if (font_count>1024 || font_count==0) return 5; 1317 | uint32_t font_index[font_count][2]; 1318 | f_seek(self->font_file, self->font_inf.Base_Addr32,SEEK_SET); 1319 | len=mp_stream_rw(self->font_file ,&font_index, font_count*8 , &errcode, MP_STREAM_RW_READ); 1320 | for(int find=0;findfont_file, font_index[find][1],SEEK_SET); 1323 | len=mp_stream_rw(self->font_file ,chr_data, 128 , &errcode, MP_STREAM_RW_READ); 1324 | if (len!=128 && errcode!=0) {return 5; } 1325 | else {return 0; } 1326 | } 1327 | } 1328 | return 6; 1329 | }else { return 6; } 1330 | break; 1331 | } 1332 | break; 1333 | default: 1334 | return 1; 1335 | break; 1336 | } 1337 | return 0; 1338 | } 1339 | 1340 | 1341 | uint32_t getasc(uint8_t f_style,uint8_t chr,uint8_t * chr_data,uint8_t * font_width,uint8_t * font_high,uint8_t * font_stride){ 1342 | switch(f_style&0x0f){ 1343 | case 0x0: 1344 | * font_width=6; 1345 | * font_high=8; 1346 | * font_stride=1; 1347 | memcpy(chr_data,&font_s_6X8[(chr - 32) * 8],8); 1348 | break; 1349 | case 0x1: 1350 | switch((f_style>>4)&0x0f){ 1351 | case 0x01: 1352 | * font_width=6; 1353 | * font_high=12; 1354 | * font_stride=1; 1355 | memcpy(chr_data,&font_s_6X12[(chr - 32) * 12],12); 1356 | break; 1357 | case 0x02: 1358 | * font_width=6; 1359 | * font_high=12; 1360 | * font_stride=1; 1361 | memcpy(chr_data,&font_c_6X12[(chr - 32) * 12],12); 1362 | break; 1363 | case 0x03: 1364 | * font_width=font_a_6X12[(chr - 32) * 26+1]; 1365 | * font_high=12; 1366 | * font_stride=2; 1367 | memcpy(chr_data,&font_a_6X12[(chr - 32) * 26+2],24); 1368 | break; 1369 | case 0x04: 1370 | * font_width=font_a_6X12[(chr - 32) * 26+1]; 1371 | * font_high=12; 1372 | * font_stride=2; 1373 | memcpy(chr_data,&font_r_6X12[(chr - 32) * 26+2],24); 1374 | break; 1375 | default : 1376 | return 1; 1377 | } 1378 | break; 1379 | case 0x2: 1380 | switch((f_style>>4)&0x0f){ 1381 | case 0x01: 1382 | * font_width=8; 1383 | * font_high=16; 1384 | * font_stride=1; 1385 | memcpy(chr_data,&font_s_8X16[(chr - 32) * 16],16); 1386 | break; 1387 | case 0x02: 1388 | * font_width=8; 1389 | * font_high=16; 1390 | * font_stride=1; 1391 | memcpy(chr_data,&font_c_8X16[(chr - 32) * 16],16); 1392 | break; 1393 | case 0x03: 1394 | * font_width=font_a_8X16[(chr - 32) * 34+1]; 1395 | * font_high=16; 1396 | * font_stride=2; 1397 | memcpy(chr_data,&font_a_8X16[(chr - 32) * 34+2],32); 1398 | break; 1399 | case 0x04: 1400 | * font_width=font_a_8X16[(chr - 32) * 34+1]; 1401 | * font_high=16; 1402 | * font_stride=2; 1403 | memcpy(chr_data,&font_r_8X16[(chr - 32) * 34+2],32); 1404 | break; 1405 | default : 1406 | return 1; 1407 | } 1408 | break; 1409 | case 0x3: 1410 | switch((f_style>>4)&0x0f){ 1411 | case 0x01: 1412 | * font_width=12; 1413 | * font_high=24; 1414 | * font_stride=2; 1415 | memcpy(chr_data,&font_s_12X24[(chr - 32) * 48],48); 1416 | break; 1417 | case 0x02: 1418 | * font_width=12; 1419 | * font_high=24; 1420 | * font_stride=2; 1421 | memcpy(chr_data,&font_c_12X24[(chr - 32) * 48],48); 1422 | break; 1423 | case 0x03: 1424 | * font_width=font_a_12X24[(chr - 32) * 74+1]; 1425 | * font_high=24; 1426 | * font_stride=3; 1427 | memcpy(chr_data,&font_a_12X24[(chr - 32) * 74+2],72); 1428 | break; 1429 | case 0x04: 1430 | * font_width=font_a_12X24[(chr - 32) * 74+1]; 1431 | * font_high=24; 1432 | * font_stride=3; 1433 | memcpy(chr_data,&font_r_12X24[(chr - 32) * 74+2],72); 1434 | break; 1435 | default : 1436 | return 1; 1437 | } 1438 | break; 1439 | case 0x4: 1440 | switch((f_style>>4)&0x0f){ 1441 | case 0x01: 1442 | * font_width=16; 1443 | * font_high=32; 1444 | * font_stride=2; 1445 | memcpy(chr_data,&font_s_16X32[(chr - 32) * 64],64); 1446 | break; 1447 | case 0x02: 1448 | * font_width=16; 1449 | * font_high=32; 1450 | * font_stride=2; 1451 | memcpy(chr_data,&font_c_16X32[(chr - 32) * 64],64); 1452 | break; 1453 | case 0x03: 1454 | * font_width=font_a_16X32[(chr - 32) * 130+1]; 1455 | * font_high=32; 1456 | * font_stride=4; 1457 | memcpy(chr_data,&font_a_16X32[(chr - 32) * 130+2],128); 1458 | break; 1459 | case 0x04: 1460 | * font_width=font_a_16X32[(chr - 32) * 130+1]; 1461 | * font_high=32; 1462 | * font_stride=4; 1463 | memcpy(chr_data,&font_r_16X32[(chr - 32) * 130+2],128); 1464 | break; 1465 | default : 1466 | return 1; 1467 | } 1468 | break; 1469 | default: 1470 | return 1; 1471 | } 1472 | return 0; 1473 | } 1474 | 1475 | STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) { 1476 | // extract arguments 1477 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 1478 | const char *str = mp_obj_str_get_str(args[1]); 1479 | mp_int_t x0 = mp_obj_get_int(args[2]); 1480 | mp_int_t y0 = mp_obj_get_int(args[3]); 1481 | mp_int_t col = 1; 1482 | uint8_t chr_data[130]; 1483 | uint32_t mask,unicode; 1484 | uint8_t utf8len; 1485 | uint8_t ret=1; 1486 | uint8_t font_width,font_high,font_stride=2; 1487 | if (n_args >= 5) { 1488 | col = mp_obj_get_int(args[4]); 1489 | } 1490 | 1491 | // loop over chars 1492 | for (; *str; ++str) { 1493 | // get char and make sure its in range of font 1494 | int chr = *(uint8_t *)str; 1495 | //panding tiaojian duqu yingwen he zhongwenziku 1496 | if (chr<0x80){ 1497 | if (chr < 32 || chr > 127) { 1498 | //mp_printf(&mp_plat_print,"%2.2X",chr); 1499 | continue; 1500 | } 1501 | ret=getasc(self->font_set.f_style,chr,chr_data,&font_width,&font_high,&font_stride); 1502 | 1503 | }else{ 1504 | if (chr>=0xC0 && chr<0xE0) { //2 1505 | utf8len=2; 1506 | unicode=(chr&0x1f)<<6*(utf8len-1); 1507 | }else if(chr>=0xE0 && chr<0xF0){ 1508 | utf8len=3; 1509 | unicode=(chr&0x0f)<<6*(utf8len-1); 1510 | }else if(chr>=0xF0 && chr<0xF8){ 1511 | utf8len=4; 1512 | unicode=(chr&0x07)<<6*(utf8len-1); 1513 | }else if(chr>=0xF8 && chr<0xFC){ 1514 | utf8len=5; 1515 | unicode=(chr&0x03)<<6*(utf8len-1); 1516 | }else if(chr>=0xFC){ 1517 | utf8len=6; 1518 | unicode=(chr&0x01)<<6*(utf8len-1); 1519 | }else { 1520 | unicode=0; 1521 | continue; 1522 | } 1523 | for (uint32_t i=0;ifont_set.rotate==0 ||self->font_set.rotate==2)&& 1542 | (x0 < self->width) && (y0 < self->height)&& 1543 | (x0 > -font_width*self->font_set.scale)&& 1544 | (y0 > -font_high*self->font_set.scale)) || 1545 | ((self->font_set.rotate==1 ||self->font_set.rotate==3)&& 1546 | (x0 < self->width) && (y0 < self->height)&& 1547 | (x0 > -font_high*self->font_set.scale)&& 1548 | (y0 > -font_width*self->font_set.scale))){ 1549 | for (int y = 0; y < font_high; y++){ 1550 | uint line_data=0; 1551 | for(int k=0;k>x))&&self->font_set.inverse==0) || 1556 | ((~line_data & (mask>>x))&&self->font_set.inverse==1)){ 1557 | // only draw if pixel set 1558 | for (int x_scale=0;x_scalefont_set.scale;x_scale++){ 1559 | for (int y_scale=0;y_scalefont_set.scale;y_scale++){ 1560 | switch(self->font_set.rotate){ 1561 | case 0: 1562 | setpixel(self, x0+x*self->font_set.scale+x_scale, y0+y*self->font_set.scale+y_scale, col); 1563 | break; 1564 | case 1: 1565 | setpixel(self, x0+font_high*self->font_set.scale-y*self->font_set.scale-y_scale, y0+x*self->font_set.scale+x_scale, col); 1566 | break; 1567 | case 2: 1568 | setpixel(self, x0+font_width*self->font_set.scale-x*self->font_set.scale-x_scale, y0+font_high*self->font_set.scale-y*self->font_set.scale-y_scale, col); 1569 | break; 1570 | case 3: 1571 | setpixel(self, x0+y*self->font_set.scale-y_scale, y0+font_width*self->font_set.scale-x*self->font_set.scale-x_scale, col); 1572 | break; 1573 | } 1574 | } 1575 | } 1576 | }else{ 1577 | if (self->font_set.transparent==0){ 1578 | for (int x_scale=0;x_scalefont_set.scale;x_scale++){ 1579 | for (int y_scale=0;y_scalefont_set.scale;y_scale++){ 1580 | switch(self->font_set.rotate){ 1581 | case 0: 1582 | setpixel(self, x0+x*self->font_set.scale+x_scale, y0+y*self->font_set.scale+y_scale, self->font_set.bg_col); 1583 | break; 1584 | case 1: 1585 | setpixel(self, x0+font_high*self->font_set.scale-y*self->font_set.scale-y_scale, y0+x*self->font_set.scale+x_scale, self->font_set.bg_col); 1586 | break; 1587 | case 2: 1588 | setpixel(self, x0+font_width*self->font_set.scale-x*self->font_set.scale-x_scale, y0+font_high*self->font_set.scale-y*self->font_set.scale-y_scale, self->font_set.bg_col); 1589 | break; 1590 | case 3: 1591 | setpixel(self, x0+y*self->font_set.scale-y_scale, y0+font_width*self->font_set.scale-x*self->font_set.scale-x_scale, self->font_set.bg_col); 1592 | break; 1593 | } 1594 | } 1595 | } 1596 | } 1597 | } 1598 | } 1599 | } 1600 | } 1601 | if ((self->font_set.rotate==0 ||self->font_set.rotate==2)){ 1602 | x0+=font_width*self->font_set.scale; 1603 | }else{ 1604 | x0+=font_high*self->font_set.scale; 1605 | } 1606 | } 1607 | } 1608 | return mp_const_none; 1609 | } 1610 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_text_obj, 4, 5, framebuf_text); 1611 | 1612 | 1613 | typedef struct __attribute__((packed)) tagBITMAPFILEHEADER 1614 | { 1615 | uint16_t bfType; 1616 | uint32_t bfSize; 1617 | uint16_t bfReserved1; 1618 | uint16_t bfReserved2; 1619 | uint32_t bfOffBits; 1620 | uint32_t biHSize; 1621 | uint32_t biWidth; 1622 | uint32_t biHeight; 1623 | uint16_t biPlanes; 1624 | uint16_t biBitcount; 1625 | uint32_t biComp; 1626 | uint32_t biPSize; 1627 | uint32_t biXPelPerMeter; 1628 | uint32_t biYPelPerMeter; 1629 | uint32_t biClrUsed; 1630 | uint32_t biClrImportant; 1631 | 1632 | } BITMAPFILEHEADER; 1633 | 1634 | STATIC mp_obj_t framebuf_show_bmp(size_t n_args, const mp_obj_t *args) { 1635 | // extract arguments 1636 | BITMAPFILEHEADER bmp_h; 1637 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 1638 | const char *filename = mp_obj_str_get_str(args[1]); 1639 | mp_int_t inv = 0; 1640 | if (n_args > 2) { 1641 | inv = mp_obj_get_int(args[2]); 1642 | } 1643 | mp_int_t x0 = 0; 1644 | mp_int_t y0 = 0; 1645 | if (n_args > 4) { 1646 | x0 = mp_obj_get_int(args[3]); 1647 | y0 = mp_obj_get_int(args[4]); 1648 | } 1649 | mp_int_t w = self->width-x0; 1650 | mp_int_t h = self->height-y0; 1651 | if (n_args > 6) { 1652 | w = MIN(mp_obj_get_int(args[5]),w); 1653 | h = MIN(mp_obj_get_int(args[6]),h); 1654 | } 1655 | mp_obj_t f_args[2] = { 1656 | mp_obj_new_str(filename, strlen(filename)), 1657 | MP_OBJ_NEW_QSTR(MP_QSTR_rb), 1658 | }; 1659 | mp_obj_t bmp_file = mp_vfs_open(MP_ARRAY_SIZE(f_args), &f_args[0], (mp_map_t *)&mp_const_empty_map); 1660 | int errcode; 1661 | int len=mp_stream_rw(bmp_file ,&bmp_h, sizeof(BITMAPFILEHEADER), &errcode, MP_STREAM_OP_READ); 1662 | if (errcode != 0 && len!=sizeof(BITMAPFILEHEADER)) { 1663 | mp_raise_OSError(errcode); 1664 | mp_printf(&mp_plat_print,"read file hard %s error!\r\n",filename); 1665 | } 1666 | if (bmp_h.bfType!=0x4d42){ 1667 | mp_printf(&mp_plat_print,"File %s not BMP.\r\n",filename); 1668 | return mp_const_none; 1669 | } 1670 | if ((self->format&0xE0)==(FRAMEBUF_RGB565&0xE0)){ 1671 | if (bmp_h.biBitcount!=0x18){ 1672 | mp_printf(&mp_plat_print,"File %s color no match.\r\n",filename); 1673 | return mp_const_none; 1674 | } 1675 | }else if(((self->format&0xE0)==(FRAMEBUF_MON_VLSB&0xE0))||((self->format&0xE0)==(FRAMEBUF_ST7302&0xE0))){ 1676 | if (bmp_h.biBitcount!=0x01){ 1677 | mp_printf(&mp_plat_print,"File %s color no match.\r\n",filename); 1678 | return mp_const_none; 1679 | } 1680 | }else if (((self->format&0xE0)==(FRAMEBUF_GS2_HMSB&0xE0)) || ((self->format&0xE0)==(FRAMEBUF_GS4_HMSB&0xE0)) \ 1681 | || ((self->format&0xE0)==(FRAMEBUF_GS8_H&0xE0))){ 1682 | if (bmp_h.biBitcount!=0x08){ 1683 | mp_printf(&mp_plat_print,"File %s color no match.\r\n",filename); 1684 | return mp_const_none; 1685 | } 1686 | }else { 1687 | mp_printf(&mp_plat_print,"Unsupported format. \r\n"); 1688 | return mp_const_none; 1689 | } 1690 | if (x0<0 && abs(x0)>bmp_h.biWidth) x0=-bmp_h.biWidth; 1691 | if (y0<0 && abs(y0)>bmp_h.biHeight) y0=-bmp_h.biHeight; 1692 | if (x0>self->width) x0=self->width; 1693 | if (y0>self->height) y0=self->height; 1694 | if (w>self->width-x0) w=self->width-x0; 1695 | if (h>self->height-y0) h=self->height-y0; 1696 | 1697 | 1698 | w=MIN(bmp_h.biWidth,w); 1699 | h=MIN(bmp_h.biHeight,h); 1700 | f_seek(bmp_file, bmp_h.bfOffBits,SEEK_SET); 1701 | if ((self->format&0xE0)==(FRAMEBUF_RGB565&0xE0)){ 1702 | uint32_t stride=(bmp_h.biWidth+3)&(~0x03); 1703 | uint8_t line_buf[stride][3]; 1704 | int32_t hh,ww; 1705 | uint16_t dot_col; 1706 | for(hh=bmp_h.biHeight;hh;hh--){ 1707 | len=mp_stream_rw(bmp_file ,&line_buf, stride*3, &errcode, MP_STREAM_OP_READ); 1708 | if (errcode != 0 && len!=stride*3) { 1709 | mp_raise_OSError(errcode); 1710 | return mp_const_none; 1711 | } 1712 | for(ww=bmp_h.biWidth;ww;ww--){ 1713 | if (ww<=w && hh<=h){ 1714 | switch(self->format&0x0F){ 1715 | case 0: 1716 | case 1: 1717 | dot_col=line_buf[ww-1][0]>>3; 1718 | dot_col|=(line_buf[ww-1][1]&0xfc)<<3; 1719 | dot_col|=(line_buf[ww-1][2]&0xf8)<<8; 1720 | setpixel(self, x0+ww-1, y0+hh-1,dot_col); 1721 | break; 1722 | case 2: 1723 | case 3: 1724 | dot_col=line_buf[ww-1][0]; 1725 | dot_col|=line_buf[ww-1][1]<<8; 1726 | dot_col|=line_buf[ww-1][2]<<16; 1727 | setpixel(self, x0+ww-1, y0+hh-1,dot_col); 1728 | } 1729 | } 1730 | } 1731 | } 1732 | }else if(((self->format&0xE0)==(FRAMEBUF_MON_VLSB&0xE0))||((self->format&0xE0)==(FRAMEBUF_ST7302&0xE0))){ 1733 | uint32_t stride=(bmp_h.biWidth+0x1F)&(~0x1F); 1734 | uint8_t line_buf[stride/8]; 1735 | int32_t hh,ww; 1736 | int32_t len; 1737 | for(hh=bmp_h.biHeight;hh;--hh){ 1738 | len=mp_stream_rw(bmp_file ,&line_buf, stride/8, &errcode, MP_STREAM_OP_READ); 1739 | if ((errcode != 0) && (len!=stride/8)){ 1740 | mp_printf(&mp_plat_print,"read file %s error!\r\n",filename); 1741 | return mp_const_none; 1742 | } 1743 | for(ww=bmp_h.biWidth;ww;--ww){ 1744 | if (ww>(ww%8)))==0){ 1746 | setpixel(self, x0+ww-1, y0+hh-1,inv?0:1); 1747 | }else{ 1748 | setpixel(self, x0+ww-1, y0+hh-1,inv?1:0); 1749 | } 1750 | } 1751 | } 1752 | } 1753 | }else if ((self->format&0xE0)==(FRAMEBUF_GS2_HMSB&0xE0)){ 1754 | uint32_t stride=(bmp_h.biWidth+0x03)&(~0x03); 1755 | uint8_t line_buf[stride]; 1756 | int32_t hh,ww; 1757 | for(hh=bmp_h.biHeight;hh;--hh){ 1758 | 1759 | len=mp_stream_rw(bmp_file ,&line_buf, stride, &errcode, MP_STREAM_OP_READ); 1760 | if ((errcode != 0) && (len!=stride)){ 1761 | mp_printf(&mp_plat_print,"read file %s error!\r\n",filename); 1762 | return mp_const_none; 1763 | } 1764 | for(ww=bmp_h.biWidth;ww;--ww){ 1765 | if (ww>6)&0x03); 1768 | }else{ 1769 | setpixel(self, x0+ww-1, y0+hh-1,((~line_buf[ww-1])>>6)&0x03); 1770 | } 1771 | } 1772 | } 1773 | } 1774 | }else if ((self->format&0xE0)==(FRAMEBUF_GS4_HMSB&0xE0)){ 1775 | uint32_t stride=(bmp_h.biWidth+0x03)&(~0x03); 1776 | uint8_t line_buf[stride]; 1777 | int32_t hh,ww; 1778 | for(hh=bmp_h.biHeight;hh;--hh){ 1779 | len=mp_stream_rw(bmp_file ,&line_buf, stride, &errcode, MP_STREAM_OP_READ); 1780 | if ((errcode != 0) && (len!=stride)){ 1781 | mp_printf(&mp_plat_print,"read file %s error!\r\n",filename); 1782 | return mp_const_none; 1783 | } 1784 | for(ww=bmp_h.biWidth;ww;--ww){ 1785 | if (ww>4)&0x0f); 1788 | }else{ 1789 | setpixel(self, x0+ww-1, y0+hh-1,((~line_buf[ww-1])>>4)&0x0f); 1790 | } 1791 | } 1792 | } 1793 | } 1794 | }else if ((self->format&0xE0)==(FRAMEBUF_GS8_V&0xE0)){ 1795 | uint32_t stride=(bmp_h.biWidth+0x03)&(~0x03); 1796 | uint8_t line_buf[stride]; 1797 | int32_t hh,ww; 1798 | for(hh=bmp_h.biHeight;hh;--hh){ 1799 | len=mp_stream_rw(bmp_file ,&line_buf, stride, &errcode, MP_STREAM_OP_READ); 1800 | if ((errcode != 0) && (len!=stride)){ 1801 | mp_printf(&mp_plat_print,"read file %s error!\r\n",filename); 1802 | return mp_const_none; 1803 | } 1804 | for(ww=bmp_h.biWidth;ww;--ww){ 1805 | if (ww= 4) { 1831 | x0 = mp_obj_get_int(args[2]); 1832 | y0 = mp_obj_get_int(args[3]); 1833 | } 1834 | mp_int_t w = self->width-x0; 1835 | mp_int_t h = self->height-y0; 1836 | if (n_args >= 6) { 1837 | w = MIN(mp_obj_get_int(args[4]),self->width-x0); 1838 | h = MIN(mp_obj_get_int(args[5]),self->height-y0); 1839 | } 1840 | 1841 | //mp_printf(&mp_plat_print,"%d,%d,%d,%d. \r\n",x0,y0,w,h); 1842 | memset(&bmp_h,0,sizeof(BITMAPFILEHEADER)); 1843 | bmp_h.bfType=0x4d42; 1844 | if (self->format==FRAMEBUF_RGB565 || self->format==FRAMEBUF_RGB565SW){ 1845 | bmp_h.bfOffBits=0x36;//dian zhen cun chu pian yi 1846 | bmp_h.biBitcount=0x18; 1847 | bmp_h.bfSize=bmp_h.bfOffBits + w*h*3; //wen jian zong chi cun 1848 | bmp_h.biPSize=w*h*3; 1849 | }else if(((self->format&0xE0)==(FRAMEBUF_MON_VLSB&0xE0))||((self->format&0xE0)==(FRAMEBUF_ST7302&0xE0))){ 1850 | bmp_h.bfOffBits=0x3e;//dian zhen cun chu pian yi 1851 | bmp_h.biBitcount=0x01; 1852 | bmp_h.bfSize=bmp_h.bfOffBits +(w+7)*h; //wen jian zong chi cun 1853 | bmp_h.biPSize=(w+7)/8*h; 1854 | }else if (((self->format&0xE0)==(FRAMEBUF_GS2_HMSB&0xE0)) || ((self->format&0xE0)==(FRAMEBUF_GS4_HMSB&0xE0)) || ((self->format&0xE0)==(FRAMEBUF_GS8_H&0xE0))){ 1855 | bmp_h.bfOffBits=0x436;//dian zhen cun chu pian yi 1856 | bmp_h.biBitcount=0x08; 1857 | bmp_h.bfSize=bmp_h.bfOffBits + w*h; //wen jian zong chi cun 1858 | bmp_h.biPSize=w*h; 1859 | }else { 1860 | mp_printf(&mp_plat_print,"Unsupported format. \r\n"); 1861 | return mp_const_none; 1862 | } 1863 | bmp_h.biComp=0x00; 1864 | bmp_h.biHSize=0x28; 1865 | bmp_h.biWidth=w; 1866 | bmp_h.biHeight=h; 1867 | bmp_h.biPlanes=1; 1868 | bmp_h.biXPelPerMeter=0; 1869 | bmp_h.biYPelPerMeter=0; 1870 | bmp_h.biClrUsed=0x100; 1871 | bmp_h.biClrImportant=0x100; 1872 | mp_obj_t f_args[2] = { 1873 | mp_obj_new_str(filename, strlen(filename)), 1874 | MP_OBJ_NEW_QSTR(MP_QSTR_wb), 1875 | }; 1876 | //mp_printf(&mp_plat_print,"open file. \r\n"); 1877 | mp_obj_t bmp_file = mp_vfs_open(MP_ARRAY_SIZE(f_args), &f_args[0], (mp_map_t *)&mp_const_empty_map); 1878 | int errcode; 1879 | //mp_printf(&mp_plat_print,"write head. \r\n"); 1880 | int len=mp_stream_rw(bmp_file ,&bmp_h, sizeof(BITMAPFILEHEADER), &errcode, MP_STREAM_OP_WRITE); 1881 | if (errcode != 0 && len!=sizeof(BITMAPFILEHEADER)) { 1882 | mp_raise_OSError(errcode); 1883 | mp_printf(&mp_plat_print,"Write %s error!\r\n",filename); 1884 | } 1885 | uint8_t buf[4]; 1886 | if (bmp_h.biBitcount==0x08){ 1887 | uint32_t clr; 1888 | for (clr=0;clr<0x100;clr++){ 1889 | buf[0]=clr; 1890 | buf[1]=clr; 1891 | buf[2]=clr; 1892 | buf[3]=0; 1893 | len=mp_stream_rw(bmp_file ,&buf, 4, &errcode, MP_STREAM_OP_WRITE); 1894 | if (errcode != 0 && len!=sizeof(BITMAPFILEHEADER)) { 1895 | mp_raise_OSError(errcode); 1896 | mp_printf(&mp_plat_print,"Write %s error!\r\n",filename); 1897 | } 1898 | } 1899 | } 1900 | if (bmp_h.biBitcount==0x01){ 1901 | uint32_t clr; 1902 | for (clr=0;clr<0x02;clr++){ 1903 | buf[0]=0xff*clr; 1904 | buf[1]=0xff*clr; 1905 | buf[2]=0xff*clr; 1906 | buf[3]=0; 1907 | len=mp_stream_rw(bmp_file ,&buf, 4, &errcode, MP_STREAM_OP_WRITE); 1908 | if (errcode != 0 && len!=sizeof(BITMAPFILEHEADER)) { 1909 | mp_raise_OSError(errcode); 1910 | mp_printf(&mp_plat_print,"Write %s error!\r\n",filename); 1911 | } 1912 | } 1913 | } 1914 | //mp_printf(&mp_plat_print,"write pixel. \r\n"); 1915 | if ((self->format&0xE0)==(FRAMEBUF_RGB565&0xE0)){ 1916 | uint32_t stride=(w+0x03)&(~0x03); 1917 | uint8_t line_buf[stride][3]; 1918 | uint32_t hh,ww; 1919 | uint16_t dot_col; 1920 | for(hh=h;hh;hh--){ 1921 | memset(&line_buf,0,stride*3); 1922 | for(ww=w;ww;ww--){ 1923 | dot_col=getpixel(self, x0+ww-1, y0+hh-1); 1924 | switch(self->format&0x0F) { 1925 | case 0: 1926 | case 1: 1927 | line_buf[ww-1][2]=(dot_col&0xf800)>>8; 1928 | line_buf[ww-1][1]=(dot_col&0x07e0)>>3; 1929 | line_buf[ww-1][0]=(dot_col&0x001e)<<3; 1930 | break; 1931 | case 2: 1932 | case 3: 1933 | line_buf[ww-1][2]=(dot_col&0xff0000)>>16; 1934 | line_buf[ww-1][1]=(dot_col&0xff00)>>8; 1935 | line_buf[ww-1][0]=(dot_col&0x00ff); 1936 | break; 1937 | } 1938 | } 1939 | len=mp_stream_rw(bmp_file ,&line_buf, stride*3, &errcode, MP_STREAM_OP_WRITE); 1940 | } 1941 | }else if(((self->format&0xE0)==(FRAMEBUF_MON_VLSB&0xE0))||((self->format&0xE0)==(FRAMEBUF_ST7302&0xE0))){ 1942 | uint32_t stride=(w+0x1F)&(~0x1F); 1943 | uint8_t line_buf[stride]; 1944 | uint32_t hh,ww; 1945 | for(hh=h;hh;--hh){ 1946 | memset(&line_buf,0,stride); 1947 | for(ww=w;ww;--ww){ 1948 | if (getpixel(self, x0+ww-1, y0+hh-1)==0) 1949 | line_buf[(ww-1)/8]|=(0x80)>>((ww-1)%8); 1950 | } 1951 | len=mp_stream_rw(bmp_file ,&line_buf, stride, &errcode, MP_STREAM_OP_WRITE); 1952 | } 1953 | }else if ((self->format&0xE0)==(FRAMEBUF_GS2_HMSB&0xE0)){ 1954 | uint32_t stride=(w+0x03)&(~0x03); 1955 | uint8_t line_buf[stride]; 1956 | uint32_t hh,ww; 1957 | for(hh=h;hh;--hh){ 1958 | memset(&line_buf,0,stride); 1959 | for(ww=w;ww;--ww){ 1960 | line_buf[(ww-1)]=getpixel(self, x0+ww-1, y0+hh-1)<<6; 1961 | } 1962 | len=mp_stream_rw(bmp_file ,&line_buf, stride, &errcode, MP_STREAM_OP_WRITE); 1963 | } 1964 | }else if ((self->format&0xE0)==(FRAMEBUF_GS4_HMSB&0xE0)){ 1965 | uint32_t stride=(w+0x03)&(~0x03); 1966 | uint8_t line_buf[stride]; 1967 | uint32_t hh,ww; 1968 | for(hh=h;hh;--hh){ 1969 | memset(&line_buf,0,stride); 1970 | for(ww=w;ww;--ww){ 1971 | line_buf[(ww-1)]=getpixel(self, x0+ww-1, y0+hh-1)<<4; 1972 | } 1973 | len=mp_stream_rw(bmp_file ,&line_buf, stride, &errcode, MP_STREAM_OP_WRITE); 1974 | } 1975 | }else if ((self->format&0xE0)==(FRAMEBUF_GS8_H&0xE0)){ 1976 | uint32_t stride=(w+0x03)&(~0x03); 1977 | uint8_t line_buf[stride]; 1978 | uint32_t hh,ww; 1979 | for(hh=h;hh;--hh){ 1980 | memset(&line_buf,0,stride); 1981 | for(ww=w;ww;--ww){ 1982 | line_buf[(ww-1)]=getpixel(self, x0+ww-1, y0+hh-1); 1983 | } 1984 | len=mp_stream_rw(bmp_file ,&line_buf, stride, &errcode, MP_STREAM_OP_WRITE); 1985 | } 1986 | } //mp_printf(&mp_plat_print,"close file. \r\n"); 1987 | mp_stream_close(bmp_file); 1988 | return mp_const_none; 1989 | } 1990 | 1991 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_save_bmp_obj, 2, 6, framebuf_save_bmp); 1992 | 1993 | 1994 | STATIC mp_obj_t framebuf_line_LUT(mp_obj_t self_in, mp_obj_t line, mp_obj_t lut_in) { 1995 | // 行转换,输入参数:行,查找表,返回行数据 1996 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in); 1997 | mp_buffer_info_t lut; 1998 | mp_get_buffer_raise(lut_in, &lut, MP_BUFFER_READ); 1999 | uint16_t line_num = mp_obj_get_int(line); 2000 | uint16_t buff[self->width]; 2001 | mp_obj_t ret_buf = mp_obj_new_bytearray(32,(uint8_t*)&buff); 2002 | uint16_t col_dot; 2003 | if (lut.len!=32) { 2004 | mp_printf(&mp_plat_print,"LUT table Error. \r\n"); 2005 | return mp_const_none; 2006 | } 2007 | if ((self->format&0xF0)==(FRAMEBUF_GS4_HMSB&0xF0)){ 2008 | for(int ww=0;wwwidth;ww++) 2009 | { 2010 | col_dot=getpixel(self, ww, line_num); 2011 | buff[ww] =((uint16_t *) lut.buf)[col_dot]; 2012 | } 2013 | } else{ 2014 | mp_printf(&mp_plat_print,"Only 4 bit mode is supported. \r\n"); 2015 | return mp_const_none; 2016 | } 2017 | return ret_buf; 2018 | } 2019 | 2020 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_line_LUT_obj, framebuf_line_LUT); 2021 | 2022 | 2023 | STATIC mp_obj_t framebuf_ToGBK(mp_obj_t self_in, mp_obj_t str_in) { 2024 | mp_obj_framebuf_t *self =MP_OBJ_TO_PTR(self_in); 2025 | uint8_t gbk_str[202]; 2026 | uint8_t gbk[2]; 2027 | uint32_t p=0; 2028 | uint32_t unicode,code_index,utf8len; 2029 | uint8_t chr; 2030 | int errcode; 2031 | const char *str = mp_obj_str_get_str(str_in); 2032 | for (; *str; ++str) { 2033 | if (p>200) break; 2034 | chr = *(uint8_t *)str; 2035 | if (chr<0x80){ 2036 | gbk_str[p] = *(uint8_t *)str; 2037 | p++; 2038 | }else{ 2039 | if (chr>=0xC0 && chr<0xE0) { //2 2040 | utf8len=2; 2041 | unicode=(chr&0x1f)<<6*(utf8len-1); 2042 | }else if(chr>=0xE0 && chr<0xF0){ 2043 | utf8len=3; 2044 | unicode=(chr&0x0f)<<6*(utf8len-1); 2045 | }else if(chr>=0xF0 && chr<0xF8){ 2046 | utf8len=4; 2047 | unicode=(chr&0x07)<<6*(utf8len-1); 2048 | }else if(chr>=0xF8 && chr<0xFC){ 2049 | utf8len=5; 2050 | unicode=(chr&0x03)<<6*(utf8len-1); 2051 | }else if(chr>=0xFC){ 2052 | utf8len=6; 2053 | unicode=(chr&0x01)<<6*(utf8len-1); 2054 | }else { 2055 | unicode=0; 2056 | continue; 2057 | } 2058 | for (uint32_t i=0;ifont_inf.Font_Type){ 2070 | case 0x1: //gb2312 2071 | case 0x2: //gbk 2072 | //printf("unicode to gbk or gb2312\r\n"); 2073 | if ((unicode>=0x000080) && (unicode<=0x00047f)){ 2074 | code_index= unicode-0x80 ; 2075 | }else if ((unicode>=0x004e00) && (unicode<=0x009fa5)){ 2076 | code_index= unicode-0x4e00+0x0d00; 2077 | }else if ((unicode>=0x00ff00) && (unicode<=0x010000)){ 2078 | code_index= unicode-0xff00+0x0C00; 2079 | }else if ((unicode>=0x003000) && (unicode<=0x0030ff)){ 2080 | code_index= unicode-0x3000+0x0B00; 2081 | }else if ((unicode>=0x002000) && (unicode<=0x0026ff)){ 2082 | code_index= unicode-0x2000+0x0400; 2083 | }else{ 2084 | continue; 2085 | } 2086 | f_seek(self->font_file, code_index *2+0x100,SEEK_SET); 2087 | int len=mp_stream_rw(self->font_file ,gbk,2, &errcode, MP_STREAM_RW_READ); 2088 | if (len==2 && errcode==0){ 2089 | gbk_str[p++] = gbk[0]; 2090 | gbk_str[p++] = gbk[1]; 2091 | } 2092 | break; 2093 | default: 2094 | mp_printf(&mp_plat_print,"To convert utf8 to gbk, you need to load a complete font library.\r\n"); 2095 | break; 2096 | } 2097 | } 2098 | } 2099 | mp_obj_t ret_buf = mp_obj_new_bytearray(p,gbk_str); 2100 | return ret_buf; 2101 | } 2102 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_ToGBK_obj, framebuf_ToGBK); 2103 | 2104 | STATIC mp_obj_t framebuf_curve(size_t n_args, const mp_obj_t *args) { 2105 | //输入数据,x,y,x_scale,y_scale,mode,col 2106 | // 2107 | // 使用列表或者bytearray输入绘制曲线 2108 | mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]); 2109 | mp_obj_t Data_obj = args[1]; 2110 | //if((mp_obj_is_type(Chart_obj, &mp_type_tuple) || mp_obj_is_type(Chart_obj, &mp_type_list))) 2111 | //mp_obj_get_array(Chart_obj, &duration_length, &duration_ptr); 2112 | 2113 | mp_buffer_info_t Data; 2114 | if (n_args > 1) { 2115 | mp_get_buffer_raise(Data_obj, &Data, MP_BUFFER_READ); 2116 | }else{ 2117 | mp_printf(&mp_plat_print,"d\r\n"); 2118 | return mp_const_none; 2119 | } 2120 | mp_int_t mode=0; 2121 | if (n_args > 2) { 2122 | mode = mp_obj_get_int(args[2]); 2123 | if (mode>2){ mode=0; } 2124 | } 2125 | mp_int_t col=0; 2126 | if (n_args > 3) { 2127 | col = mp_obj_get_int(args[3]); 2128 | } 2129 | mp_int_t x0 = 0; 2130 | mp_int_t y0 = self->height/2; 2131 | if (n_args > 5) { 2132 | x0 = mp_obj_get_int(args[4]); 2133 | y0 = mp_obj_get_int(args[5]); 2134 | } 2135 | mp_int_t x_scale = 1; 2136 | if (n_args > 6) { 2137 | x_scale = mp_obj_get_int(args[6]); 2138 | } 2139 | mp_int_t y_scale = self->height/2; 2140 | if (n_args > 7) { 2141 | y_scale = mp_obj_get_int(args[7]); 2142 | } 2143 | mp_int_t lenght=0; 2144 | mp_int_t y_shift=0; 2145 | if ((Data.typecode==BYTEARRAY_TYPECODE) || (Data.typecode=='B')){ 2146 | lenght=Data.len; 2147 | y_shift=256; 2148 | }else if (Data.typecode=='b'){ 2149 | lenght=Data.len; 2150 | y_shift=128; 2151 | }else if (Data.typecode=='H') { 2152 | lenght=Data.len/2; 2153 | y_shift=65536; 2154 | }else if(Data.typecode=='h'){ 2155 | lenght=Data.len/2; 2156 | y_shift=32768; 2157 | }else{ 2158 | mp_printf(&mp_plat_print,"input buffer must in B b H h\r\n"); 2159 | return mp_const_none; 2160 | } 2161 | 2162 | mp_int_t prev=0; 2163 | mp_int_t curr=0; 2164 | for (int count=0;count0){ 2172 | line(self,x0+(count-1)*x_scale,y0+prev*y_scale/y_shift,x0+count*x_scale,y0+curr*y_scale/y_shift,col); 2173 | } 2174 | prev=curr; 2175 | break; 2176 | case 2: 2177 | if (curr>0){ 2178 | fill_rect(self,(x0+count)*x_scale,y0,x_scale,abs(curr*y_scale/y_shift),col); 2179 | }else{ 2180 | fill_rect(self,(x0+count)*x_scale,y0+curr*y_scale/y_shift,x_scale,abs(curr*y_scale/y_shift),col); 2181 | } 2182 | break; 2183 | } 2184 | } 2185 | return mp_const_none; 2186 | } 2187 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_curve_obj, 2, 8, framebuf_curve); 2188 | #if !MICROPY_ENABLE_DYNRUNTIME 2189 | STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = { 2190 | { MP_ROM_QSTR(MP_QSTR_show_bmp), MP_ROM_PTR(&framebuf_show_bmp_obj) }, 2191 | { MP_ROM_QSTR(MP_QSTR_save_bmp), MP_ROM_PTR(&framebuf_save_bmp_obj) }, 2192 | { MP_ROM_QSTR(MP_QSTR_font_load), MP_ROM_PTR(&framebuf_font_load_obj) }, 2193 | { MP_ROM_QSTR(MP_QSTR_font_free), MP_ROM_PTR(&framebuf_font_free_obj) }, 2194 | { MP_ROM_QSTR(MP_QSTR_font_set), MP_ROM_PTR(&framebuf_font_set_obj) }, 2195 | { MP_ROM_QSTR(MP_QSTR_ToGBK), MP_ROM_PTR(&framebuf_ToGBK_obj) }, 2196 | { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&framebuf_fill_obj) }, 2197 | { MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&framebuf_fill_rect_obj) }, 2198 | { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&framebuf_pixel_obj) }, 2199 | { MP_ROM_QSTR(MP_QSTR_hline), MP_ROM_PTR(&framebuf_hline_obj) }, 2200 | { MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) }, 2201 | { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) }, 2202 | { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) }, 2203 | { MP_ROM_QSTR(MP_QSTR_ellipse), MP_ROM_PTR(&framebuf_ellipse_obj) }, 2204 | #if MICROPY_PY_ARRAY 2205 | { MP_ROM_QSTR(MP_QSTR_poly), MP_ROM_PTR(&framebuf_poly_obj) }, 2206 | { MP_ROM_QSTR(MP_QSTR_curve), MP_ROM_PTR(&framebuf_curve_obj) }, 2207 | #endif 2208 | { MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) }, 2209 | { MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) }, 2210 | { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) }, 2211 | { MP_ROM_QSTR(MP_QSTR_line_LUT), MP_ROM_PTR(&framebuf_line_LUT_obj) }, 2212 | 2213 | }; 2214 | STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table); 2215 | 2216 | STATIC MP_DEFINE_CONST_OBJ_TYPE( 2217 | mp_type_framebuf, 2218 | MP_QSTR_FrameBuffer, 2219 | MP_TYPE_FLAG_NONE, 2220 | make_new, framebuf_make_new, 2221 | buffer, framebuf_get_buffer, 2222 | locals_dict, &framebuf_locals_dict 2223 | ); 2224 | 2225 | 2226 | #endif 2227 | 2228 | // this factory function is provided for backwards compatibility with old FrameBuffer1 class 2229 | STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) { 2230 | mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t); 2231 | o->base.type = &mp_type_framebuf; 2232 | 2233 | mp_buffer_info_t bufinfo; 2234 | mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE); 2235 | o->buf = bufinfo.buf; 2236 | 2237 | o->width = mp_obj_get_int(args[1]); 2238 | o->height = mp_obj_get_int(args[2]); 2239 | o->format = FRAMEBUF_MON_VLSB; 2240 | if (n_args >= 4) { 2241 | o->stride = mp_obj_get_int(args[3]); 2242 | } else { 2243 | o->stride = o->width; 2244 | } 2245 | 2246 | return MP_OBJ_FROM_PTR(o); 2247 | } 2248 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1); 2249 | 2250 | #if !MICROPY_ENABLE_DYNRUNTIME 2251 | STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = { 2252 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) }, 2253 | { MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) }, 2254 | { MP_ROM_QSTR(MP_QSTR_FrameBuffer1), MP_ROM_PTR(&legacy_framebuffer1_obj) }, 2255 | { MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MON_HLSB) }, 2256 | { MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MON_HMSB) }, 2257 | { MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MON_VLSB) }, 2258 | { MP_ROM_QSTR(MP_QSTR_MONO_VMSB), MP_ROM_INT(FRAMEBUF_MON_VMSB) }, 2259 | { MP_ROM_QSTR(MP_QSTR_GS2_HLSB), MP_ROM_INT(FRAMEBUF_GS2_HLSB) }, 2260 | { MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) }, 2261 | { MP_ROM_QSTR(MP_QSTR_GS2_VLSB), MP_ROM_INT(FRAMEBUF_GS2_VLSB) }, 2262 | { MP_ROM_QSTR(MP_QSTR_GS2_VMSB), MP_ROM_INT(FRAMEBUF_GS2_VMSB) }, 2263 | { MP_ROM_QSTR(MP_QSTR_GS4_HLSB), MP_ROM_INT(FRAMEBUF_GS4_HLSB) }, 2264 | { MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) }, 2265 | { MP_ROM_QSTR(MP_QSTR_GS4_VLSB), MP_ROM_INT(FRAMEBUF_GS4_VLSB) }, 2266 | { MP_ROM_QSTR(MP_QSTR_GS4_VMSB), MP_ROM_INT(FRAMEBUF_GS4_VMSB) }, 2267 | { MP_ROM_QSTR(MP_QSTR_GS8_H), MP_ROM_INT(FRAMEBUF_GS8_H) }, 2268 | { MP_ROM_QSTR(MP_QSTR_GS8_V), MP_ROM_INT(FRAMEBUF_GS8_V) }, 2269 | { MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) }, 2270 | { MP_ROM_QSTR(MP_QSTR_RGB565SW), MP_ROM_INT(FRAMEBUF_RGB565SW) }, 2271 | { MP_ROM_QSTR(MP_QSTR_RGB888), MP_ROM_INT(FRAMEBUF_RGB888) }, 2272 | { MP_ROM_QSTR(MP_QSTR_RGB8888), MP_ROM_INT(FRAMEBUF_RGB8888) }, 2273 | { MP_ROM_QSTR(MP_QSTR_ST7302), MP_ROM_INT(FRAMEBUF_ST7302) }, 2274 | { MP_ROM_QSTR(MP_QSTR_MX), MP_ROM_INT(FRAMEBUF_MX) }, 2275 | { MP_ROM_QSTR(MP_QSTR_MY), MP_ROM_INT(FRAMEBUF_MY) }, 2276 | { MP_ROM_QSTR(MP_QSTR_MV), MP_ROM_INT(FRAMEBUF_MV) }, 2277 | 2278 | { MP_ROM_QSTR(MP_QSTR_Font_S12), MP_ROM_INT(Font_S12) }, 2279 | { MP_ROM_QSTR(MP_QSTR_Font_C12), MP_ROM_INT(Font_C12) }, 2280 | { MP_ROM_QSTR(MP_QSTR_Font_A12), MP_ROM_INT(Font_A12) }, 2281 | { MP_ROM_QSTR(MP_QSTR_Font_R12), MP_ROM_INT(Font_R12) }, 2282 | 2283 | { MP_ROM_QSTR(MP_QSTR_Font_S16), MP_ROM_INT(Font_S16) }, 2284 | { MP_ROM_QSTR(MP_QSTR_Font_C16), MP_ROM_INT(Font_C16) }, 2285 | { MP_ROM_QSTR(MP_QSTR_Font_A16), MP_ROM_INT(Font_A16) }, 2286 | { MP_ROM_QSTR(MP_QSTR_Font_R16), MP_ROM_INT(Font_R16) }, 2287 | 2288 | { MP_ROM_QSTR(MP_QSTR_Font_S24), MP_ROM_INT(Font_S24) }, 2289 | { MP_ROM_QSTR(MP_QSTR_Font_C24), MP_ROM_INT(Font_C24) }, 2290 | { MP_ROM_QSTR(MP_QSTR_Font_A24), MP_ROM_INT(Font_A24) }, 2291 | { MP_ROM_QSTR(MP_QSTR_Font_R24), MP_ROM_INT(Font_R24) }, 2292 | 2293 | { MP_ROM_QSTR(MP_QSTR_Font_S32), MP_ROM_INT(Font_S32) }, 2294 | { MP_ROM_QSTR(MP_QSTR_Font_C32), MP_ROM_INT(Font_C32) }, 2295 | { MP_ROM_QSTR(MP_QSTR_Font_A32), MP_ROM_INT(Font_A32) }, 2296 | { MP_ROM_QSTR(MP_QSTR_Font_R32), MP_ROM_INT(Font_R32) } 2297 | 2298 | }; 2299 | 2300 | STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table); 2301 | 2302 | const mp_obj_module_t mp_module_framebuf = { 2303 | .base = { &mp_type_module }, 2304 | .globals = (mp_obj_dict_t *)&framebuf_module_globals, 2305 | }; 2306 | 2307 | MP_REGISTER_MODULE(MP_QSTR_framebuf, mp_module_framebuf); 2308 | #endif 2309 | 2310 | #endif // MICROPY_PY_FRAMEBUF 2311 | --------------------------------------------------------------------------------