diff --git a/components/micropython/port/src/omv/img/draw.c b/components/micropython/port/src/omv/img/draw.c index 6982ec9eb..0f6055e49 100644 --- a/components/micropython/port/src/omv/img/draw.c +++ b/components/micropython/port/src/omv/img/draw.c @@ -268,8 +268,25 @@ void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotati scratch_draw_rotated_ellipse(img, cx, cy, rx * 2, ry * 2, rotation, fill, c, thickness); } -void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space) +void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space, + int char_rotation, bool char_hmirror, bool char_vflip, int string_rotation, bool string_hmirror, bool string_vflip) { + char_rotation %= 360; + if (char_rotation < 0) char_rotation += 360; + char_rotation = (char_rotation / 90) * 90; + + string_rotation %= 360; + if (string_rotation < 0) string_rotation += 360; + string_rotation = (string_rotation / 90) * 90; + + bool char_swap_w_h = (char_rotation == 90) || (char_rotation == 270); + bool char_upsidedown = (char_rotation == 180) || (char_rotation == 270); + + if (string_hmirror) x_off -= fast_floorf(font[0].w * scale) - 1; + if (string_vflip) y_off -= fast_floorf(font[0].h * scale) - 1; + + int org_x_off = x_off; + int org_y_off = y_off; const int anchor = x_off; for(char ch, last = '\0'; (ch = *str); str++, last = ch) { @@ -280,17 +297,11 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int if ((ch == '\n') || (ch == '\r')) { // handle '\n' or '\r' strings x_off = anchor; - y_off += fast_roundf(font[0].h * scale) + y_spacing; // newline height == space height + y_off += (string_vflip ? -1 : +1) * (fast_floorf((char_swap_w_h ? font[0].w : font[0].h) * scale) + y_spacing); // newline height == space height continue; } if ((ch < ' ') || (ch > '~')) { // handle unknown characters - imlib_draw_rectangle(img, - x_off + (fast_roundf(scale * 3) / 2), - y_off + (fast_roundf(scale * 3) / 2), - fast_roundf(font[0].w * scale) - ((fast_roundf(scale * 3) / 2) * 2), - fast_roundf(font[0].h * scale) - ((fast_roundf(scale * 3) / 2) * 2), - c, fast_roundf(scale), false); continue; } @@ -300,46 +311,81 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int // Find the first pixel set and offset to that. bool exit = false; - for (int x = 0, xx = g->w; x < xx; x++) { - for (int y = 0, yy = g->h; y < yy; y++) { - if (g->data[y] & (1 << (g->w - 1 - x))) { - x_off -= fast_roundf(x * scale); - exit = true; - break; + if (!char_swap_w_h) { + for (int x = 0, xx = g->w; x < xx; x++) { + for (int y = 0, yy = g->h; y < yy; y++) { + if (g->data[(char_upsidedown ^ char_vflip) ? (g->h - 1 - y) : y] & + (1 << ((char_upsidedown ^ char_hmirror ^ string_hmirror) ? x : (g->w - 1 - x)))) { + x_off += (string_hmirror ? +1 : -1) * fast_floorf(x * scale); + exit = true; + break; + } } + + if (exit) break; } + } else { + for (int y = g->h - 1; y >= 0; y--) { + for (int x = 0, xx = g->w; x < xx; x++) { + if (g->data[(char_upsidedown ^ char_vflip) ? (g->h - 1 - y) : y] & + (1 << ((char_upsidedown ^ char_hmirror ^ string_hmirror) ? x : (g->w - 1 - x)))) { + x_off += (string_hmirror ? +1 : -1) * fast_floorf((g->h - 1 - y) * scale); + exit = true; + break; + } + } - if (exit) break; + if (exit) break; + } } } - for (int y = 0, yy = fast_roundf(g->h * scale); y < yy; y++) { - for (int x = 0, xx = fast_roundf(g->w * scale); x < xx; x++) { - if (g->data[fast_roundf(y / scale)] & (1 << (g->w - 1 - fast_roundf(x / scale)))) { - imlib_set_pixel(img, (x_off + x), (y_off + y), c); + for (int y = 0, yy = fast_floorf(g->h * scale); y < yy; y++) { + for (int x = 0, xx = fast_floorf(g->w * scale); x < xx; x++) { + if (g->data[fast_floorf(y / scale)] & (1 << (g->w - 1 - fast_floorf(x / scale)))) { + int16_t x_tmp = x_off + (char_hmirror ? (xx - x - 1) : x), y_tmp = y_off + (char_vflip ? (yy - y - 1) : y); + point_rotate(x_tmp, y_tmp, IM_DEG2RAD(char_rotation), x_off + (xx / 2), y_off + (yy / 2), &x_tmp, &y_tmp); + point_rotate(x_tmp, y_tmp, IM_DEG2RAD(string_rotation), org_x_off, org_y_off, &x_tmp, &y_tmp); + imlib_set_pixel(img, x_tmp, y_tmp, c); } } } if (mono_space) { - x_off += fast_roundf(g->w * scale) + x_spacing; + x_off += (string_hmirror ? -1 : +1) * (fast_floorf((char_swap_w_h ? g->h : g->w) * scale) + x_spacing); } else { // Find the last pixel set and offset to that. bool exit = false; - for (int x = g->w - 1; x >= 0; x--) { - for (int y = g->h - 1; y >= 0; y--) { - if (g->data[y] & (1 << (g->w - 1 - x))) { - x_off += fast_roundf((x + 2) * scale) + x_spacing; - exit = true; - break; + if (!char_swap_w_h) { + for (int x = g->w - 1; x >= 0; x--) { + for (int y = g->h - 1; y >= 0; y--) { + if (g->data[(char_upsidedown ^ char_vflip) ? (g->h - 1 - y) : y] & + (1 << ((char_upsidedown ^ char_hmirror ^ string_hmirror) ? x : (g->w - 1 - x)))) { + x_off += (string_hmirror ? -1 : +1) * (fast_floorf((x + 2) * scale) + x_spacing); + exit = true; + break; + } } + + if (exit) break; } + } else { + for (int y = 0, yy = g->h; y < yy; y++) { + for (int x = g->w - 1; x >= 0; x--) { + if (g->data[(char_upsidedown ^ char_vflip) ? (g->h - 1 - y) : y] & + (1 << ((char_upsidedown ^ char_hmirror ^ string_hmirror) ? x : (g->w - 1 - x)))) { + x_off += (string_hmirror ? -1 : +1) * (fast_floorf(((g->h - 1 - y) + 2) * scale) + x_spacing); + exit = true; + break; + } + } - if (exit) break; + if (exit) break; + } } - if (!exit) x_off += fast_roundf(scale * 3); // space char + if (!exit) x_off += (string_hmirror ? -1 : +1) * fast_floorf(scale * 3); // space char } } }