mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-17 01:02:12 +00:00
FS-7506 FS-7513: refactor with rgb color space to support anti aliasing
This commit is contained in:
parent
a446d8411e
commit
90ea86bc95
@ -50,7 +50,11 @@ typedef struct switch_yuv_color_s {
|
|||||||
uint8_t v;
|
uint8_t v;
|
||||||
} switch_yuv_color_t;
|
} switch_yuv_color_t;
|
||||||
|
|
||||||
|
typedef struct switch_rgb_color_s {
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
} switch_rgb_color_t;
|
||||||
|
|
||||||
/**\brief Representation of a rectangle on a surface */
|
/**\brief Representation of a rectangle on a surface */
|
||||||
typedef struct switch_image_rect {
|
typedef struct switch_image_rect {
|
||||||
@ -164,26 +168,28 @@ SWITCH_DECLARE(void) switch_img_flip(switch_image_t *img);
|
|||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(void) switch_img_free(switch_image_t **img);
|
SWITCH_DECLARE(void) switch_img_free(switch_image_t **img);
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_img_draw_text(switch_image_t *IMG, int x, int y, switch_yuv_color_t color, uint16_t font_size, char *text);
|
SWITCH_DECLARE(void) switch_img_draw_text(switch_image_t *IMG, int x, int y, switch_rgb_color_t color, uint16_t font_size, char *text);
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_img_add_text(void *buffer, int w, int x, int y, char *s);
|
SWITCH_DECLARE(void) switch_img_add_text(void *buffer, int w, int x, int y, char *s);
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, int x, int y, int w, int h);
|
SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, int x, int y, int w, int h);
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_img_fill(switch_image_t *img, int x, int y, int w, int h, switch_yuv_color_t color);
|
SWITCH_DECLARE(void) switch_img_fill(switch_image_t *img, int x, int y, int w, int h, switch_rgb_color_t *color);
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_img_draw_pixel(switch_image_t *img, int x, int y, switch_yuv_color_t color);
|
SWITCH_DECLARE(void) switch_img_draw_pixel(switch_image_t *img, int x, int y, switch_yuv_color_t *color);
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_color_set(switch_yuv_color_t *color, const char *color_str);
|
SWITCH_DECLARE(void) switch_color_set_rgb(switch_rgb_color_t *color, const char *color_str);
|
||||||
|
SWITCH_DECLARE(void) switch_color_set_yuv(switch_yuv_color_t *color, const char *color_str);
|
||||||
|
SWITCH_DECLARE(void) switch_color_rgb2yuv(switch_rgb_color_t *rgb, switch_yuv_color_t *yuv);
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_create(switch_img_txt_handle_t **handleP, const char *font_family,
|
SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_create(switch_img_txt_handle_t **handleP, const char *font_family,
|
||||||
const char *font_color, uint16_t font_size, double angle, switch_memory_pool_t *pool);
|
const char *font_color, const char *bgcolor, uint16_t font_size, double angle, switch_memory_pool_t *pool);
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_img_txt_handle_destroy(switch_img_txt_handle_t **handleP);
|
SWITCH_DECLARE(void) switch_img_txt_handle_destroy(switch_img_txt_handle_t **handleP);
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_render(switch_img_txt_handle_t *handle, switch_image_t *img,
|
SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_render(switch_img_txt_handle_t *handle, switch_image_t *img,
|
||||||
int x, int y, const char *text,
|
int x, int y, const char *text,
|
||||||
const char *font_family, const char *font_color, uint16_t font_size, double angle);
|
const char *font_family, const char *font_color, const char *bgcolor, uint16_t font_size, double angle);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ typedef struct mcu_canvas_s {
|
|||||||
int total_layers;
|
int total_layers;
|
||||||
int layers_used;
|
int layers_used;
|
||||||
int layout_floor_id;
|
int layout_floor_id;
|
||||||
switch_yuv_color_t bgcolor;
|
switch_rgb_color_t bgcolor;
|
||||||
switch_mutex_t *mutex;
|
switch_mutex_t *mutex;
|
||||||
switch_mutex_t *cond_mutex;
|
switch_mutex_t *cond_mutex;
|
||||||
switch_mutex_t *cond2_mutex;
|
switch_mutex_t *cond2_mutex;
|
||||||
@ -891,9 +891,9 @@ static int mcu_canvas_wake(mcu_canvas_t *mcu_canvas)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reset_image(switch_image_t *img, switch_yuv_color_t *color)
|
static void reset_image(switch_image_t *img, switch_rgb_color_t *color)
|
||||||
{
|
{
|
||||||
switch_img_fill(img, 0, 0, img->w, img->h, *color);
|
switch_img_fill(img, 0, 0, img->w, img->h, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SCALE_FACTOR 360.0f
|
#define SCALE_FACTOR 360.0f
|
||||||
@ -1004,7 +1004,7 @@ static void scale_and_patch(conference_obj_t *conference, mcu_layer_t *layer)
|
|||||||
|
|
||||||
static void set_canvas_bgcolor(mcu_canvas_t *canvas, char *color)
|
static void set_canvas_bgcolor(mcu_canvas_t *canvas, char *color)
|
||||||
{
|
{
|
||||||
switch_color_set(&canvas->bgcolor, color);
|
switch_color_set_rgb(&canvas->bgcolor, color);
|
||||||
reset_image(canvas->img, &canvas->bgcolor);
|
reset_image(canvas->img, &canvas->bgcolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1051,7 +1051,7 @@ static void detach_video_layer(conference_member_t *member)
|
|||||||
|
|
||||||
static void layer_set_banner(mcu_canvas_t *canvas, mcu_layer_t *layer, const char *text)
|
static void layer_set_banner(mcu_canvas_t *canvas, mcu_layer_t *layer, const char *text)
|
||||||
{
|
{
|
||||||
switch_yuv_color_t fgcolor, bgcolor;
|
switch_rgb_color_t fgcolor, bgcolor;
|
||||||
int font_scale = 4;
|
int font_scale = 4;
|
||||||
int font_size = 0;
|
int font_size = 0;
|
||||||
const char *fg = "#cccccc";
|
const char *fg = "#cccccc";
|
||||||
@ -1099,8 +1099,8 @@ static void layer_set_banner(mcu_canvas_t *canvas, mcu_layer_t *layer, const cha
|
|||||||
font_size = (double)(font_scale / 100.0f) * layer->screen_h;
|
font_size = (double)(font_scale / 100.0f) * layer->screen_h;
|
||||||
|
|
||||||
|
|
||||||
switch_color_set(&fgcolor, fg);
|
switch_color_set_rgb(&fgcolor, fg);
|
||||||
switch_color_set(&bgcolor, bg);
|
switch_color_set_rgb(&bgcolor, bg);
|
||||||
|
|
||||||
switch_img_free(&layer->banner_img);
|
switch_img_free(&layer->banner_img);
|
||||||
layer->banner_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, layer->screen_w, font_size * 2, 1);
|
layer->banner_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, layer->screen_w, font_size * 2, 1);
|
||||||
@ -1110,10 +1110,10 @@ static void layer_set_banner(mcu_canvas_t *canvas, mcu_layer_t *layer, const cha
|
|||||||
switch_img_txt_handle_destroy(&layer->txthandle);
|
switch_img_txt_handle_destroy(&layer->txthandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_img_txt_handle_create(&layer->txthandle, font_face, fg, font_size, 0, NULL);
|
switch_img_txt_handle_create(&layer->txthandle, font_face, fg, "#000000", font_size, 0, NULL);
|
||||||
|
|
||||||
reset_image(layer->banner_img, &bgcolor);
|
reset_image(layer->banner_img, &bgcolor);
|
||||||
switch_img_txt_handle_render(layer->txthandle, layer->banner_img, font_size / 2, font_size / 2, text, NULL, NULL, 0, 0);
|
switch_img_txt_handle_render(layer->txthandle, layer->banner_img, font_size / 2, font_size / 2, text, NULL, NULL, NULL, 0, 0);
|
||||||
|
|
||||||
if (params) switch_event_destroy(¶ms);
|
if (params) switch_event_destroy(¶ms);
|
||||||
switch_safe_free(dup);
|
switch_safe_free(dup);
|
||||||
@ -1126,7 +1126,7 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
|
|||||||
const char *res_id = NULL;
|
const char *res_id = NULL;
|
||||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
const char *banner = NULL;
|
const char *banner = NULL;
|
||||||
switch_yuv_color_t color;
|
switch_rgb_color_t color;
|
||||||
|
|
||||||
if (!member->session) abort();
|
if (!member->session) abort();
|
||||||
|
|
||||||
@ -1169,8 +1169,8 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch_color_set(&color, "#000000");
|
switch_color_set_rgb(&color, "#000000");
|
||||||
switch_img_fill(member->conference->canvas->img, layer->x_pos, layer->y_pos, layer->screen_w, layer->screen_h, color);
|
switch_img_fill(member->conference->canvas->img, layer->x_pos, layer->y_pos, layer->screen_w, layer->screen_h, &color);
|
||||||
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@ -1541,19 +1541,19 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0) {
|
if (1) {
|
||||||
switch_img_txt_handle_t *txthandle = NULL;
|
switch_img_txt_handle_t *txthandle = NULL;
|
||||||
switch_yuv_color_t color;
|
switch_rgb_color_t color;
|
||||||
|
|
||||||
switch_img_txt_handle_create(&txthandle, "/usr/share/fonts/truetype/Microsoft/Verdana.ttf",
|
switch_img_txt_handle_create(&txthandle, "/usr/share/fonts/truetype/Microsoft/Verdana.ttf",
|
||||||
"#FFFFFF", 24, 0, NULL);
|
"#FFFFFF", "#000000", 24, 0, NULL);
|
||||||
|
|
||||||
switch_img_txt_handle_render(txthandle, conference->canvas->img, 10, 10, "W00t this works!", NULL, NULL, 0, 0);
|
switch_img_txt_handle_render(txthandle, conference->canvas->img, 10, 10, "W00t this works!", NULL, NULL, NULL, 0, 0);
|
||||||
|
|
||||||
switch_color_set(&color, "#FF0000");
|
switch_color_set_rgb(&color, "#FF0000");
|
||||||
switch_img_fill(conference->canvas->img, 300, 10, 400, 40, color);
|
switch_img_fill(conference->canvas->img, 300, 10, 400, 40, &color);
|
||||||
|
|
||||||
switch_img_txt_handle_render(txthandle, conference->canvas->img, 300, 22, "W00t this works!", NULL, NULL, 0, 0);
|
switch_img_txt_handle_render(txthandle, conference->canvas->img, 300, 22, "W00t this works!", NULL, NULL, "#FF0000", 0, 0);
|
||||||
|
|
||||||
switch_img_txt_handle_destroy(&txthandle);
|
switch_img_txt_handle_destroy(&txthandle);
|
||||||
|
|
||||||
|
@ -163,36 +163,39 @@ SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, int x
|
|||||||
return new_img;
|
return new_img;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_img_draw_pixel(switch_image_t *img, int x, int y, switch_yuv_color_t color)
|
SWITCH_DECLARE(void) switch_img_draw_pixel(switch_image_t *img, int x, int y, switch_yuv_color_t *color)
|
||||||
{
|
{
|
||||||
if (x < 0 || y < 0 || x >= img->d_w || y >= img->d_h) return;
|
if (x < 0 || y < 0 || x >= img->d_w || y >= img->d_h) return;
|
||||||
|
|
||||||
img->planes[SWITCH_PLANE_Y][y * img->stride[SWITCH_PLANE_Y] + x] = color.y;
|
img->planes[SWITCH_PLANE_Y][y * img->stride[SWITCH_PLANE_Y] + x] = color->y;
|
||||||
|
|
||||||
if (((x & 0x1) == 0) && ((y & 0x1) == 0)) {// only draw on even position
|
if (((x & 0x1) == 0) && ((y & 0x1) == 0)) {// only draw on even position
|
||||||
img->planes[SWITCH_PLANE_U][y / 2 * img->stride[SWITCH_PLANE_U] + x / 2] = color.u;
|
img->planes[SWITCH_PLANE_U][y / 2 * img->stride[SWITCH_PLANE_U] + x / 2] = color->u;
|
||||||
img->planes[SWITCH_PLANE_V][y / 2 * img->stride[SWITCH_PLANE_V] + x / 2] = color.v;
|
img->planes[SWITCH_PLANE_V][y / 2 * img->stride[SWITCH_PLANE_V] + x / 2] = color->v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_img_fill(switch_image_t *img, int x, int y, int w, int h, switch_yuv_color_t color)
|
SWITCH_DECLARE(void) switch_img_fill(switch_image_t *img, int x, int y, int w, int h, switch_rgb_color_t *color)
|
||||||
{
|
{
|
||||||
int len, i;
|
int len, i;
|
||||||
|
switch_yuv_color_t yuv_color;
|
||||||
|
|
||||||
if (x < 0 || y < 0 || x >= img->d_w || y >= img->d_h) return;
|
if (x < 0 || y < 0 || x >= img->d_w || y >= img->d_h) return;
|
||||||
|
|
||||||
|
switch_color_rgb2yuv(color, &yuv_color);
|
||||||
|
|
||||||
len = MIN(w, img->d_w - x);
|
len = MIN(w, img->d_w - x);
|
||||||
if (len <= 0) return;
|
if (len <= 0) return;
|
||||||
|
|
||||||
for (i = y; i < (y + h) && i < img->d_h; i++) {
|
for (i = y; i < (y + h) && i < img->d_h; i++) {
|
||||||
memset(img->planes[SWITCH_PLANE_Y] + img->stride[SWITCH_PLANE_Y] * i + x, color.y, len);
|
memset(img->planes[SWITCH_PLANE_Y] + img->stride[SWITCH_PLANE_Y] * i + x, yuv_color.y, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
len /= 2;
|
len /= 2;
|
||||||
|
|
||||||
for (i = y; i < (y + h) && i < img->d_h; i += 2) {
|
for (i = y; i < (y + h) && i < img->d_h; i += 2) {
|
||||||
memset(img->planes[SWITCH_PLANE_U] + img->stride[SWITCH_PLANE_U] * i / 2 + x / 2, color.u, len);
|
memset(img->planes[SWITCH_PLANE_U] + img->stride[SWITCH_PLANE_U] * i / 2 + x / 2, yuv_color.u, len);
|
||||||
memset(img->planes[SWITCH_PLANE_V] + img->stride[SWITCH_PLANE_V] * i / 2 + x / 2, color.v, len);
|
memset(img->planes[SWITCH_PLANE_V] + img->stride[SWITCH_PLANE_V] * i / 2 + x / 2, yuv_color.v, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,56 +252,88 @@ SWITCH_DECLARE(void) switch_img_add_text(void *buffer, int w, int x, int y, char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_color_set(switch_yuv_color_t *color, const char *color_str)
|
SWITCH_DECLARE(void) switch_color_set_rgb(switch_rgb_color_t *color, const char *str)
|
||||||
{
|
{
|
||||||
uint8_t y = 134;
|
if (zstr(str)) return;
|
||||||
uint8_t u = 128;
|
|
||||||
uint8_t v = 124;
|
|
||||||
|
|
||||||
if (color_str != NULL && strlen(color_str) == 7) {
|
if ((*str) == '#' && strlen(str) == 7) {
|
||||||
uint8_t red, green, blue;
|
unsigned int r, g, b;
|
||||||
char str[7];
|
sscanf(str, "#%02x%02x%02x", &r, &g, &b);
|
||||||
int i;
|
color->r = r;
|
||||||
|
color->g = g;
|
||||||
color_str++;
|
color->b = b;
|
||||||
strncpy(str, color_str, 6);
|
} else {
|
||||||
for(i = 0; i < 6; i++) {
|
if (!strcmp(str, "red")) {
|
||||||
str[i] = switch_toupper(str[i]);
|
color->r = 255;
|
||||||
|
color->g = 0;
|
||||||
|
color->b = 0;
|
||||||
|
} else if (!strcmp(str, "green")) {
|
||||||
|
color->r = 0;
|
||||||
|
color->g = 255;
|
||||||
|
color->b = 0;
|
||||||
|
} else if (!strcmp(str, "blue")) {
|
||||||
|
color->r = 0;
|
||||||
|
color->g = 0;
|
||||||
|
color->b = 255;
|
||||||
}
|
}
|
||||||
red = (str[0] >= 'A' ? (str[0] - 'A' + 10) * 16 : (str[0] - '0') * 16) + (str[1] >= 'A' ? (str[1] - 'A' + 10) : (str[0] - '0'));
|
|
||||||
green = (str[2] >= 'A' ? (str[2] - 'A' + 10) * 16 : (str[2] - '0') * 16) + (str[3] >= 'A' ? (str[3] - 'A' + 10) : (str[0] - '0'));
|
|
||||||
blue = (str[4] >= 'A' ? (str[4] - 'A' + 10) * 16 : (str[4] - '0') * 16) + (str[5] >= 'A' ? (str[5] - 'A' + 10) : (str[0] - '0'));
|
|
||||||
|
|
||||||
y = (uint8_t)(((red * 4897) >> 14) + ((green * 9611) >> 14) + ((blue * 1876) >> 14));
|
|
||||||
u = (uint8_t)(- ((red * 2766) >> 14) - ((5426 * green) >> 14) + blue / 2 + 128);
|
|
||||||
v = (uint8_t)(red / 2 -((6855 * green) >> 14) - ((blue * 1337) >> 14) + 128);
|
|
||||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "set color, red = %u, green = %u, blue = %u, y = %u, u = %u, v = %u\n", red, green, blue, y, u, v);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
color->y = y;
|
SWITCH_DECLARE(void) switch_color_rgb2yuv(switch_rgb_color_t *rgb, switch_yuv_color_t *yuv)
|
||||||
color->u = u;
|
{
|
||||||
color->v = v;
|
yuv->y = (uint8_t)(((rgb->r * 4897) >> 14) + ((rgb->g * 9611) >> 14) + ((rgb->b * 1876) >> 14));
|
||||||
|
yuv->u = (uint8_t)(- ((rgb->r * 2766) >> 14) - ((5426 * rgb->g) >> 14) + rgb->b / 2 + 128);
|
||||||
|
yuv->v = (uint8_t)(rgb->r / 2 -((6855 * rgb->b) >> 14) - ((rgb->b * 1337) >> 14) + 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(void) switch_color_set_yuv(switch_yuv_color_t *color, const char *str)
|
||||||
|
{
|
||||||
|
switch_rgb_color_t rgb = { 0 };
|
||||||
|
|
||||||
|
switch_color_set_rgb(&rgb, str);
|
||||||
|
switch_color_rgb2yuv(&rgb, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
#include FT_GLYPH_H
|
#include FT_GLYPH_H
|
||||||
|
|
||||||
|
#define MAX_GRADIENT 8
|
||||||
|
|
||||||
struct switch_img_txt_handle_s {
|
struct switch_img_txt_handle_s {
|
||||||
FT_Library library;
|
FT_Library library;
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
char *font_family;
|
char *font_family;
|
||||||
double angle;
|
double angle;
|
||||||
uint16_t font_size;
|
uint16_t font_size;
|
||||||
switch_yuv_color_t color;
|
switch_rgb_color_t color;
|
||||||
|
switch_rgb_color_t bgcolor;
|
||||||
switch_image_t *img;
|
switch_image_t *img;
|
||||||
switch_memory_pool_t *pool;
|
switch_memory_pool_t *pool;
|
||||||
int free_pool;
|
int free_pool;
|
||||||
|
switch_yuv_color_t gradient_table[MAX_GRADIENT];
|
||||||
|
switch_bool_t use_bgcolor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void init_gradient_table(switch_img_txt_handle_t *handle)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
switch_rgb_color_t color;
|
||||||
|
|
||||||
|
switch_rgb_color_t *c1 = &handle->bgcolor;
|
||||||
|
switch_rgb_color_t *c2 = &handle->color;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_GRADIENT; i++) {
|
||||||
|
color.r = c1->r + (c2->r - c1->r) * i / MAX_GRADIENT;
|
||||||
|
color.g = c1->g + (c2->g - c1->g) * i / MAX_GRADIENT;
|
||||||
|
color.b = c1->b + (c2->b - c1->b) * i / MAX_GRADIENT;
|
||||||
|
|
||||||
|
switch_color_rgb2yuv(&color, &handle->gradient_table[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_create(switch_img_txt_handle_t **handleP, const char *font_family,
|
SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_create(switch_img_txt_handle_t **handleP, const char *font_family,
|
||||||
const char *font_color, uint16_t font_size, double angle, switch_memory_pool_t *pool)
|
const char *font_color, const char *bgcolor, uint16_t font_size, double angle, switch_memory_pool_t *pool)
|
||||||
{
|
{
|
||||||
int free_pool = 0;
|
int free_pool = 0;
|
||||||
switch_img_txt_handle_t *new_handle;
|
switch_img_txt_handle_t *new_handle;
|
||||||
@ -320,7 +355,10 @@ SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_create(switch_img_txt_hand
|
|||||||
new_handle->font_size = font_size;
|
new_handle->font_size = font_size;
|
||||||
new_handle->angle = angle;
|
new_handle->angle = angle;
|
||||||
|
|
||||||
switch_color_set(&new_handle->color, font_color);
|
switch_color_set_rgb(&new_handle->color, font_color);
|
||||||
|
switch_color_set_rgb(&new_handle->bgcolor, bgcolor);
|
||||||
|
|
||||||
|
init_gradient_table(new_handle);
|
||||||
|
|
||||||
*handleP = new_handle;
|
*handleP = new_handle;
|
||||||
|
|
||||||
@ -350,19 +388,24 @@ SWITCH_DECLARE(void) switch_img_txt_handle_destroy(switch_img_txt_handle_t **han
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_bitmap(switch_image_t *img, FT_Bitmap* bitmap, FT_Int x, FT_Int y, switch_yuv_color_t color)
|
static void draw_bitmap(switch_img_txt_handle_t *handle, switch_image_t *img, FT_Bitmap* bitmap, FT_Int x, FT_Int y)
|
||||||
{
|
{
|
||||||
FT_Int i, j, p, q;
|
FT_Int i, j, p, q;
|
||||||
FT_Int x_max = x + bitmap->width;
|
FT_Int x_max = x + bitmap->width;
|
||||||
FT_Int y_max = y + bitmap->rows;
|
FT_Int y_max = y + bitmap->rows;
|
||||||
|
switch_yuv_color_t yuv_color;
|
||||||
|
|
||||||
if (bitmap->width == 0) return;
|
if (bitmap->width == 0) return;
|
||||||
|
|
||||||
|
switch_color_rgb2yuv(&handle->color, &yuv_color);
|
||||||
|
|
||||||
switch (bitmap->pixel_mode) {
|
switch (bitmap->pixel_mode) {
|
||||||
case FT_PIXEL_MODE_GRAY: // it should always be GRAY since we use FT_LOAD_RENDER?
|
case FT_PIXEL_MODE_GRAY: // it should always be GRAY since we use FT_LOAD_RENDER?
|
||||||
break;
|
break;
|
||||||
case FT_PIXEL_MODE_NONE:
|
case FT_PIXEL_MODE_NONE:
|
||||||
case FT_PIXEL_MODE_MONO:
|
case FT_PIXEL_MODE_MONO:
|
||||||
|
{
|
||||||
|
|
||||||
for ( j = y, q = 0; j < y_max; j++, q++ ) {
|
for ( j = y, q = 0; j < y_max; j++, q++ ) {
|
||||||
for ( i = x, p = 0; i < x_max; i++, p++ ) {
|
for ( i = x, p = 0; i < x_max; i++, p++ ) {
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
@ -372,11 +415,12 @@ static void draw_bitmap(switch_image_t *img, FT_Bitmap* bitmap, FT_Int x, FT_Int
|
|||||||
|
|
||||||
byte = bitmap->buffer[(q * linesize + p) / 8];
|
byte = bitmap->buffer[(q * linesize + p) / 8];
|
||||||
if ((byte >> (7 - (p % 8))) & 0x1) {
|
if ((byte >> (7 - (p % 8))) & 0x1) {
|
||||||
switch_img_draw_pixel(img, i, j, color);
|
switch_img_draw_pixel(img, i, j, &yuv_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
case FT_PIXEL_MODE_GRAY2:
|
case FT_PIXEL_MODE_GRAY2:
|
||||||
case FT_PIXEL_MODE_GRAY4:
|
case FT_PIXEL_MODE_GRAY4:
|
||||||
case FT_PIXEL_MODE_LCD:
|
case FT_PIXEL_MODE_LCD:
|
||||||
@ -387,10 +431,15 @@ static void draw_bitmap(switch_image_t *img, FT_Bitmap* bitmap, FT_Int x, FT_Int
|
|||||||
|
|
||||||
for ( i = x, p = 0; i < x_max; i++, p++ ) {
|
for ( i = x, p = 0; i < x_max; i++, p++ ) {
|
||||||
for ( j = y, q = 0; j < y_max; j++, q++ ) {
|
for ( j = y, q = 0; j < y_max; j++, q++ ) {
|
||||||
|
int gradient = bitmap->buffer[q * bitmap->width + p];
|
||||||
if ( i < 0 || j < 0 || i >= img->d_w || j >= img->d_h) continue;
|
if ( i < 0 || j < 0 || i >= img->d_w || j >= img->d_h) continue;
|
||||||
|
|
||||||
if (bitmap->buffer[q * bitmap->width + p] > 128) {
|
if (handle->use_bgcolor) {
|
||||||
switch_img_draw_pixel(img, i, j, color);
|
switch_img_draw_pixel(img, i, j, &handle->gradient_table[gradient * MAX_GRADIENT / 256]);
|
||||||
|
} else {
|
||||||
|
if (gradient > 128) {
|
||||||
|
switch_img_draw_pixel(img, i, j, &yuv_color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,13 +448,13 @@ static void draw_bitmap(switch_image_t *img, FT_Bitmap* bitmap, FT_Int x, FT_Int
|
|||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_render(switch_img_txt_handle_t *handle, switch_image_t *img,
|
SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_render(switch_img_txt_handle_t *handle, switch_image_t *img,
|
||||||
int x, int y, const char *text,
|
int x, int y, const char *text,
|
||||||
const char *font_family, const char *font_color, uint16_t font_size, double angle)
|
const char *font_family, const char *font_color, const char *bgcolor, uint16_t font_size, double angle)
|
||||||
{
|
{
|
||||||
FT_GlyphSlot slot;
|
FT_GlyphSlot slot;
|
||||||
FT_Matrix matrix; /* transformation matrix */
|
FT_Matrix matrix; /* transformation matrix */
|
||||||
FT_Vector pen; /* untransformed origin */
|
FT_Vector pen; /* untransformed origin */
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
int target_height;
|
//int target_height;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
FT_ULong ch;
|
FT_ULong ch;
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
@ -425,14 +474,21 @@ SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_render(switch_img_txt_hand
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (font_color) {
|
if (font_color) {
|
||||||
switch_color_set(&handle->color, font_color);
|
switch_color_set_rgb(&handle->color, font_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bgcolor) {
|
||||||
|
switch_color_set_rgb(&handle->bgcolor, bgcolor);
|
||||||
|
handle->use_bgcolor = SWITCH_TRUE;
|
||||||
|
} else {
|
||||||
|
handle->use_bgcolor = SWITCH_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->angle = angle;
|
handle->angle = angle;
|
||||||
|
|
||||||
//angle = 0; (45.0 / 360 ) * 3.14159 * 2;
|
//angle = 0; (45.0 / 360 ) * 3.14159 * 2;
|
||||||
|
|
||||||
target_height = img->d_h;
|
//target_height = img->d_h;
|
||||||
|
|
||||||
error = FT_New_Face(handle->library, font_family, 0, &face); /* create face object */
|
error = FT_New_Face(handle->library, font_family, 0, &face); /* create face object */
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -446,6 +502,10 @@ SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_render(switch_img_txt_hand
|
|||||||
|
|
||||||
slot = face->glyph;
|
slot = face->glyph;
|
||||||
|
|
||||||
|
if (handle->use_bgcolor && slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO) {
|
||||||
|
init_gradient_table(handle);
|
||||||
|
}
|
||||||
|
|
||||||
/* set up matrix */
|
/* set up matrix */
|
||||||
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
|
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
|
||||||
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
|
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
|
||||||
@ -472,7 +532,7 @@ SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_render(switch_img_txt_hand
|
|||||||
if (error) continue;
|
if (error) continue;
|
||||||
|
|
||||||
/* now, draw to our target surface (convert position) */
|
/* now, draw to our target surface (convert position) */
|
||||||
draw_bitmap(img, &slot->bitmap, pen.x + slot->bitmap_left, pen.y - slot->bitmap_top + font_size, handle->color);
|
draw_bitmap(handle, img, &slot->bitmap, pen.x + slot->bitmap_left, pen.y - slot->bitmap_top + font_size);
|
||||||
|
|
||||||
/* increment pen position */
|
/* increment pen position */
|
||||||
pen.x += slot->advance.x >> 6;
|
pen.x += slot->advance.x >> 6;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user