00001
00038 #include <stddef.h>
00039 #include <assert.h>
00040 #ifdef CONFIG_HUGEMEM
00041 #include <hugemem.h>
00042 #endif
00043
00044 #include <gfx/gfx.h>
00045
00046 #ifndef CONFIG_FONT_PIXELS_PER_BYTE
00047 # define CONFIG_FONT_PIXELS_PER_BYTE 8
00048 #endif
00049
00050 #define EXTMEM_BUF_SIZE 20
00051
00052 #if defined(CONFIG_HUGEMEM) || defined(__DOXYGEN__)
00053
00067 static void gfx_draw_char_hugemem(char ch, gfx_coord_t x, gfx_coord_t y,
00068 struct font *font, gfx_color_t color, gfx_color_t background_color)
00069 {
00070 uint8_t i;
00071 uint8_t char_row_size;
00072 uint8_t glyph_size;
00073 uint16_t glyph_data_offset;
00074 uint8_t char_buff[EXTMEM_BUF_SIZE];
00075 uint8_t buffer_pos;
00076 uint8_t scale = font->scale;
00077 uint8_t rows_left;
00078
00079 gfx_coord_t inc_x = x;
00080 gfx_coord_t inc_y = y;
00081
00082 char_row_size = font->width / CONFIG_FONT_PIXELS_PER_BYTE;
00083 if (font->width % CONFIG_FONT_PIXELS_PER_BYTE)
00084 char_row_size++;
00085
00086 glyph_size = char_row_size * font->height;
00087 glyph_data_offset = glyph_size * ((uint8_t)ch - font->first_char);
00088 buffer_pos = EXTMEM_BUF_SIZE;
00089 rows_left = font->height;
00090
00091 do {
00092 static uint8_t glyph_byte = 0;
00093 uint8_t pixelsToDraw = font->width;
00094
00095 for (i = 0; i < pixelsToDraw; i++) {
00096 if (i % CONFIG_FONT_PIXELS_PER_BYTE == 0) {
00097
00098 if (buffer_pos >= EXTMEM_BUF_SIZE) {
00099 hugemem_ptr_t source =
00100 font->data.hugemem;
00101 source = (hugemem_ptr_t)
00102 ((uint32_t)source +
00103 glyph_data_offset);
00104
00105 hugemem_read_block(char_buff, source,
00106 EXTMEM_BUF_SIZE);
00107
00108 glyph_data_offset += EXTMEM_BUF_SIZE;
00109 buffer_pos = 0;
00110 }
00111
00112 glyph_byte = char_buff[buffer_pos];
00113 buffer_pos++;
00114 }
00115
00116
00117 if ((glyph_byte & 0x80)) {
00118 if (scale == 1)
00119 gfx_draw_pixel(inc_x, inc_y, color);
00120 else
00121 gfx_draw_filled_rect(inc_x, inc_y,
00122 scale, scale, color);
00123 }
00124
00125 inc_x += scale;
00126 glyph_byte <<= 1;
00127 }
00128
00129 inc_y += scale;
00130 inc_x = x;
00131 } while (--rows_left > 0);
00132 }
00133 #endif
00134
00149 static void gfx_draw_char_progmem(char ch, gfx_coord_t x, gfx_coord_t y,
00150 struct font *font, gfx_color_t color,
00151 gfx_color_t background_color)
00152 {
00153 const uint8_t __progmem_arg *glyph_data;
00154 uint16_t glyph_data_offset;
00155 uint8_t scale = font->scale;
00156 uint8_t char_row_size;
00157 uint8_t rows_left;
00158 uint8_t i;
00159
00160 gfx_coord_t inc_x = x;
00161 gfx_coord_t inc_y = y;
00162
00163 char_row_size = font->width / CONFIG_FONT_PIXELS_PER_BYTE;
00164 if (font->width % CONFIG_FONT_PIXELS_PER_BYTE)
00165 char_row_size++;
00166
00167 glyph_data_offset = char_row_size * font->height *
00168 ((uint8_t)ch - font->first_char);
00169 glyph_data = font->data.progmem + glyph_data_offset;
00170 rows_left = font->height;
00171
00172 do {
00173 uint8_t glyph_byte = 0;
00174 uint8_t pixelsToDraw = font->width;
00175
00176 for (i = 0; i < pixelsToDraw; i++) {
00177 if (i % CONFIG_FONT_PIXELS_PER_BYTE == 0) {
00178 glyph_byte = progmem_read8(glyph_data);
00179 glyph_data++;
00180 }
00181
00182 if ((glyph_byte & 0x80)) {
00183 if (scale == 1)
00184 gfx_draw_pixel(inc_x, inc_y, color);
00185 else
00186 gfx_draw_filled_rect(inc_x, inc_y,
00187 scale, scale, color);
00188 }
00189
00190 inc_x += scale;
00191 glyph_byte <<= 1;
00192 }
00193
00194 inc_y += scale;
00195 inc_x = x;
00196 rows_left--;
00197 } while (rows_left > 0);
00198 }
00199
00200 void gfx_draw_char(char c, gfx_coord_t x, gfx_coord_t y, struct font* font,
00201 gfx_color_t color, gfx_color_t background_color)
00202 {
00203
00204 if ((uint8_t)c < font->first_char)
00205 c = font->first_char;
00206 if ((uint8_t)c > font->last_char)
00207 c = font->last_char;
00208
00209 assert(font->scale > 0);
00210
00211
00212 if (background_color != GFX_COLOR_TRANSPARENT) {
00213 gfx_draw_filled_rect(x, y, font->width * font->scale,
00214 font->height * font->scale, background_color);
00215 }
00216
00217 switch (font->type) {
00218 case FONT_LOC_PROGMEM:
00219 gfx_draw_char_progmem(c, x, y, font, color, background_color);
00220 break;
00221 #ifdef CONFIG_HUGEMEM
00222 case FONT_LOC_HUGEMEM:
00223 gfx_draw_char_hugemem(c, x, y, font, color, background_color);
00224 break;
00225 #endif
00226 default:
00227
00228 unhandled_case(font->type);
00229 break;
00230 }
00231 }
00232
00233 void gfx_draw_string(char* str, gfx_coord_t x, gfx_coord_t y, struct font* font,
00234 gfx_color_t color, gfx_color_t background_color)
00235 {
00236 uint8_t scale = font->scale;
00237
00238
00239 gfx_coord_t const start_of_string_position_x = x;
00240
00241
00242 assert(scale > 0);
00243 assert(font);
00244 assert(str);
00245
00246
00247 do {
00248
00249 if (*str == '\n') {
00250 x = start_of_string_position_x;
00251 y += font->height * scale;
00252 }
00253 else if (*str == '\r') {
00254
00255 } else {
00256 gfx_draw_char(*str, x, y, font, color,
00257 background_color);
00258 x += font->width * scale;
00259 }
00260 } while (*(++str));
00261 }
00262
00263 void gfx_draw_progmem_string(const char __progmem_arg *str, gfx_coord_t x,
00264 gfx_coord_t y, struct font *font, gfx_color_t color,
00265 gfx_color_t background_color)
00266 {
00267 char temp_char;
00268 uint8_t scale = font->scale;
00269
00270 assert(scale > 0);
00271 assert(font);
00272 assert(str);
00273
00274
00275 gfx_coord_t const start_of_string_position_x = x;
00276
00277
00278 temp_char = progmem_read8((uint8_t __progmem_arg *)str);
00279
00280 while (temp_char) {
00281
00282 if (temp_char == '\n') {
00283 x = start_of_string_position_x;
00284 y += font->height * scale;
00285 }
00286 else if (*str == '\r') {
00287
00288 } else {
00289 gfx_draw_char(temp_char, x, y, font, color,
00290 background_color);
00291 x += font->width * scale;
00292 }
00293
00294 temp_char = progmem_read8((uint8_t __progmem_arg *)(++str));
00295 }
00296 }
00297
00298 void gfx_get_string_bounding_box(char const *str, struct font *font,
00299 gfx_coord_t * width, gfx_coord_t * height)
00300 {
00301 gfx_coord_t font_width = font->width * font->scale;
00302 gfx_coord_t font_height = font->height * font->scale;
00303
00304 gfx_coord_t max_width = 1;
00305 gfx_coord_t max_height = font_height;
00306 gfx_coord_t x = 0;
00307
00308 assert(str);
00309 assert(font);
00310 assert(width);
00311 assert(height);
00312
00313
00314 do {
00315
00316 if (*str == '\n') {
00317 x = 0;
00318 max_height += font_height;
00319 }
00320 else if (*str == '\r') {
00321
00322 } else {
00323 x += font_width;
00324 if (x > max_width)
00325 max_width = x;
00326 }
00327 } while (*(++str));
00328
00329
00330 *width = max_width;
00331 *height = max_height;
00332 }
00333
00334 void gfx_get_progmem_string_bounding_box(const char __progmem_arg *str,
00335 struct font *font, gfx_coord_t *width, gfx_coord_t *height)
00336 {
00337 gfx_coord_t font_width = font->width * font->scale;
00338 gfx_coord_t font_height = font->height * font->scale;
00339
00340 char temp_char;
00341 gfx_coord_t max_width = 1;
00342 gfx_coord_t max_height = font_height;
00343 gfx_coord_t x = 0;
00344
00345 assert(str);
00346 assert(font);
00347 assert(width);
00348 assert(height);
00349
00350
00351 temp_char = progmem_read8((uint8_t __progmem_arg *)str);
00352
00353 while (temp_char) {
00354
00355 if (temp_char == '\n') {
00356 x = 0;
00357 max_height += font_height;
00358 }
00359 else if (*str == '\r') {
00360
00361 } else {
00362 x += font_width;
00363 if (x > max_width)
00364 max_width = x;
00365 }
00366
00367 temp_char = progmem_read8((uint8_t __progmem_arg *)(++str));
00368 }
00369
00370
00371 *width = max_width;
00372 *height = max_height;
00373 }