mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Upgrade text drawing to support rotations of the character and string.
This commit is contained in:
parent
ee321933d2
commit
cd586f66bc
@ -24,6 +24,10 @@ while(True):
|
||||
|
||||
# If the first argument is a scaler then this method expects
|
||||
# to see x, y, and text. Otherwise, it expects a (x,y,text) tuple.
|
||||
img.draw_string(x, y, "Hello World!", color = (r, g, b), scale = 2, mono_space = False)
|
||||
|
||||
# Character and string rotation can be done at 0, 90, 180, 270, and etc. degrees.
|
||||
img.draw_string(x, y, "Hello World!", color = (r, g, b), scale = 2, mono_space = False,
|
||||
char_rotation = 0, char_hmirror = False, char_vflip = False,
|
||||
string_rotation = 0, string_hmirror = False, string_vflip = False)
|
||||
|
||||
print(clock.fps())
|
||||
|
||||
@ -288,8 +288,27 @@ 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, r, 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)
|
||||
// char rotation == 0, 90, 180, 360, etc.
|
||||
// string rotation == 0, 90, 180, 360, etc.
|
||||
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) {
|
||||
@ -300,17 +319,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_floorf(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_floorf(scale * 3) / 2),
|
||||
y_off + (fast_floorf(scale * 3) / 2),
|
||||
fast_floorf(font[0].w * scale) - ((fast_floorf(scale * 3) / 2) * 2),
|
||||
fast_floorf(font[0].h * scale) - ((fast_floorf(scale * 3) / 2) * 2),
|
||||
c, fast_floorf(scale), false);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -320,46 +333,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_floorf(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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)))) {
|
||||
imlib_set_pixel(img, (x_off + x), (y_off + y), c);
|
||||
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_floorf(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_floorf((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;
|
||||
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) x_off += fast_floorf(scale * 3); // space char
|
||||
if (!exit) x_off += (string_hmirror ? -1 : +1) * fast_floorf(scale * 3); // space char
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1262,7 +1262,8 @@ void imlib_draw_line(image_t *img, int x0, int y0, int x1, int y1, int c, int th
|
||||
void imlib_draw_rectangle(image_t *img, int rx, int ry, int rw, int rh, int c, int thickness, bool fill);
|
||||
void imlib_draw_circle(image_t *img, int cx, int cy, int r, int c, int thickness, bool fill);
|
||||
void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotation, int c, int thickness, bool fill);
|
||||
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_hflip);
|
||||
void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float x_scale, float y_scale, float alpha, image_t *mask);
|
||||
void imlib_flood_fill(image_t *img, int x, int y,
|
||||
float seed_threshold, float floating_threshold,
|
||||
|
||||
@ -1706,10 +1706,23 @@ STATIC mp_obj_t py_image_draw_string(uint n_args, const mp_obj_t *args, mp_map_t
|
||||
py_helper_keyword_int(n_args, args, offset + 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_spacing), 0);
|
||||
bool arg_mono_space =
|
||||
py_helper_keyword_int(n_args, args, offset + 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mono_space), true);
|
||||
int arg_char_rotation =
|
||||
py_helper_keyword_int(n_args, args, offset + 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_char_rotation), 0);
|
||||
int arg_char_hmirror =
|
||||
py_helper_keyword_int(n_args, args, offset + 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_char_hmirror), false);
|
||||
int arg_char_vflip =
|
||||
py_helper_keyword_int(n_args, args, offset + 7, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_char_vflip), false);
|
||||
int arg_string_rotation =
|
||||
py_helper_keyword_int(n_args, args, offset + 8, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_string_rotation), 0);
|
||||
int arg_string_hmirror =
|
||||
py_helper_keyword_int(n_args, args, offset + 9, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_string_hmirror), false);
|
||||
int arg_string_vflip =
|
||||
py_helper_keyword_int(n_args, args, offset + 10, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_string_vflip), false);
|
||||
|
||||
imlib_draw_string(arg_img, arg_x_off, arg_y_off, arg_str,
|
||||
arg_c, arg_scale, arg_x_spacing, arg_y_spacing,
|
||||
arg_mono_space);
|
||||
arg_c, arg_scale, arg_x_spacing, arg_y_spacing, arg_mono_space,
|
||||
arg_char_rotation, arg_char_hmirror, arg_char_vflip,
|
||||
arg_string_rotation, arg_string_hmirror, arg_string_vflip);
|
||||
return args[0];
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_string_obj, 2, py_image_draw_string);
|
||||
|
||||
@ -463,6 +463,12 @@ Q(draw_string)
|
||||
Q(x_spacing)
|
||||
Q(y_spacing)
|
||||
Q(mono_space)
|
||||
Q(char_rotation)
|
||||
Q(char_hmirror)
|
||||
Q(char_vflip)
|
||||
Q(string_rotation)
|
||||
Q(string_hmirror)
|
||||
Q(string_vflip)
|
||||
|
||||
// Draw Cross
|
||||
Q(draw_cross)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user