Upgrade text drawing to support rotations of the character and string.

This commit is contained in:
Kwabena W. Agyeman 2019-02-16 21:18:20 -05:00
parent ee321933d2
commit cd586f66bc
5 changed files with 103 additions and 31 deletions

View File

@ -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())

View File

@ -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
}
}
}

View File

@ -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,

View File

@ -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);

View File

@ -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)