22 changed files with 8993 additions and 159 deletions
			
			
		@ -0,0 +1,87 @@
				@@ -0,0 +1,87 @@
					 | 
				
			||||
#include <stddef.h> | 
				
			||||
#include <stdint.h> | 
				
			||||
#include <string.h> | 
				
			||||
#include <stdlib.h> | 
				
			||||
 | 
				
			||||
#include "base64.h" | 
				
			||||
 | 
				
			||||
static const unsigned char decoding_table[256] = { | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f, | 
				
			||||
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, | 
				
			||||
    0x3c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, | 
				
			||||
    0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 
				
			||||
    0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, | 
				
			||||
    0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, | 
				
			||||
    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, | 
				
			||||
    0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, | 
				
			||||
    0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
				
			||||
}; | 
				
			||||
 | 
				
			||||
char* base64_decode(const char *data) { | 
				
			||||
    size_t input_length = strlen(data); | 
				
			||||
    if (input_length % 4 != 0) { | 
				
			||||
        return NULL; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    size_t output_length = input_length / 4 * 3; | 
				
			||||
 | 
				
			||||
    if (data[input_length - 1] == '=') { | 
				
			||||
        (output_length)--; | 
				
			||||
    } | 
				
			||||
    if (data[input_length - 2] == '=') { | 
				
			||||
        (output_length)--; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    unsigned char* output = (unsigned char *)malloc(output_length + 1); | 
				
			||||
    if (output == NULL) { | 
				
			||||
        return NULL; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    for (int i = 0, j = 0; i < (int)input_length;) { | 
				
			||||
        uint32_t sextet_a = (data[i] == '=') ? (0 & i++) : decoding_table[(unsigned char)(data[i++])]; | 
				
			||||
        uint32_t sextet_b = (data[i] == '=') ? (0 & i++) : decoding_table[(unsigned char)(data[i++])]; | 
				
			||||
        uint32_t sextet_c = (data[i] == '=') ? (0 & i++) : decoding_table[(unsigned char)(data[i++])]; | 
				
			||||
        uint32_t sextet_d = (data[i] == '=') ? (0 & i++) : decoding_table[(unsigned char)(data[i++])]; | 
				
			||||
 | 
				
			||||
        uint32_t triple = (sextet_a << 3 * 6) | 
				
			||||
            + (sextet_b << 2 * 6) | 
				
			||||
            + (sextet_c << 1 * 6) | 
				
			||||
            + (sextet_d << 0 * 6); | 
				
			||||
 | 
				
			||||
        if (j < (int)output_length) { | 
				
			||||
            output[j++] = (triple >> 2 * 8) & 0xFF; | 
				
			||||
        } | 
				
			||||
        if (j < (int)output_length) { | 
				
			||||
            output[j++] = (triple >> 1 * 8) & 0xFF; | 
				
			||||
        } | 
				
			||||
        if (j < (int)output_length) { | 
				
			||||
            output[j++] = (triple >> 0 * 8) & 0xFF; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    output[output_length] = 0x00; | 
				
			||||
    return (char *)output; | 
				
			||||
}; | 
				
			||||
@ -0,0 +1,6 @@
				@@ -0,0 +1,6 @@
					 | 
				
			||||
#ifndef __BASE64_H__ | 
				
			||||
#define __BASE64_H__ | 
				
			||||
 | 
				
			||||
char* base64_decode(const char *data); | 
				
			||||
 | 
				
			||||
#endif | 
				
			||||
@ -0,0 +1,171 @@
				@@ -0,0 +1,171 @@
					 | 
				
			||||
#include <time.h> | 
				
			||||
 | 
				
			||||
#include <ft2build.h> | 
				
			||||
#include FT_FREETYPE_H | 
				
			||||
 | 
				
			||||
#include "text_font.h" | 
				
			||||
#include "text.h" | 
				
			||||
 | 
				
			||||
static char errbuf[256]; | 
				
			||||
 | 
				
			||||
static void set_error(const char *format, ...) { | 
				
			||||
    va_list args; | 
				
			||||
    va_start(args, format); | 
				
			||||
    vsnprintf(errbuf, 256, format, args); | 
				
			||||
} | 
				
			||||
 | 
				
			||||
const char *text_get_error() { | 
				
			||||
    return errbuf; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
typedef struct { | 
				
			||||
    bool enabled; | 
				
			||||
    char *text_overlay; | 
				
			||||
    FT_Library library; | 
				
			||||
    FT_Face face; | 
				
			||||
} text_priv_t; | 
				
			||||
 | 
				
			||||
bool text_create(const parameters_t *params, text_t **text) { | 
				
			||||
    *text = malloc(sizeof(text_priv_t)); | 
				
			||||
    text_priv_t *textp = (text_priv_t *)(*text); | 
				
			||||
    memset(textp, 0, sizeof(text_priv_t)); | 
				
			||||
 | 
				
			||||
    textp->enabled = params->text_overlay_enable; | 
				
			||||
    textp->text_overlay = strdup(params->text_overlay); | 
				
			||||
 | 
				
			||||
    if (textp->enabled) { | 
				
			||||
        int error = FT_Init_FreeType(&textp->library); | 
				
			||||
        if (error) { | 
				
			||||
            set_error("FT_Init_FreeType() failed"); | 
				
			||||
            goto failed; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        error = FT_New_Memory_Face( | 
				
			||||
            textp->library, | 
				
			||||
            IBMPlexMono_Medium, | 
				
			||||
            sizeof(IBMPlexMono_Medium), | 
				
			||||
            0, | 
				
			||||
            &textp->face); | 
				
			||||
        if (error) { | 
				
			||||
            set_error("FT_New_Memory_Face() failed"); | 
				
			||||
            goto failed; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        error = FT_Set_Pixel_Sizes( | 
				
			||||
            textp->face, | 
				
			||||
            25, | 
				
			||||
            25); | 
				
			||||
        if (error) { | 
				
			||||
            set_error("FT_Set_Pixel_Sizes() failed"); | 
				
			||||
            goto failed; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    return true; | 
				
			||||
 | 
				
			||||
failed: | 
				
			||||
    free(textp); | 
				
			||||
 | 
				
			||||
    return false; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
static void draw_rect(uint8_t *buf, int stride, int height, int x, int y, unsigned int rect_width, unsigned int rect_height) { | 
				
			||||
    uint8_t *Y = buf; | 
				
			||||
    uint8_t *U = Y + stride * height; | 
				
			||||
    uint8_t *V = U + (stride / 2) * (height / 2); | 
				
			||||
    const uint8_t color[3] = {0, 128, 128}; | 
				
			||||
    uint32_t opacity = 45; | 
				
			||||
 | 
				
			||||
    for (unsigned int src_y = 0; src_y < rect_height; src_y++) { | 
				
			||||
        for (unsigned int src_x = 0; src_x < rect_width; src_x++) { | 
				
			||||
            unsigned int dest_x = x + src_x; | 
				
			||||
            unsigned int dest_y = y + src_y; | 
				
			||||
            int i1 = dest_y*stride + dest_x; | 
				
			||||
            int i2 = dest_y/2*stride/2 + dest_x/2; | 
				
			||||
 | 
				
			||||
            Y[i1] = ((color[0] * opacity) + (uint32_t)Y[i1] * (255 - opacity)) / 255; | 
				
			||||
            U[i2] = ((color[1] * opacity) + (uint32_t)U[i2] * (255 - opacity)) / 255; | 
				
			||||
            V[i2] = ((color[2] * opacity) + (uint32_t)V[i2] * (255 - opacity)) / 255; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
static void draw_bitmap(uint8_t *buf, int stride, int height, const FT_Bitmap *bitmap, int x, int y) { | 
				
			||||
    uint8_t *Y = buf; | 
				
			||||
    uint8_t *U = Y + stride * height; | 
				
			||||
    uint8_t *V = U + (stride / 2) * (height / 2); | 
				
			||||
 | 
				
			||||
    for (unsigned int src_y = 0; src_y < bitmap->rows; src_y++) { | 
				
			||||
        for (unsigned int src_x = 0; src_x < bitmap->width; src_x++) { | 
				
			||||
            uint8_t v = bitmap->buffer[src_y*bitmap->pitch + src_x]; | 
				
			||||
 | 
				
			||||
            if (v != 0) { | 
				
			||||
                unsigned int dest_x = x + src_x; | 
				
			||||
                unsigned int dest_y = y + src_y; | 
				
			||||
                int i1 = dest_y*stride + dest_x; | 
				
			||||
                int i2 = dest_y/2*stride/2 + dest_x/2; | 
				
			||||
                uint32_t opacity = (uint32_t)v; | 
				
			||||
 | 
				
			||||
                Y[i1] = (uint8_t)(((uint32_t)v * opacity + (uint32_t)Y[i1] * (255 - opacity)) / 255); | 
				
			||||
                U[i2] = (uint8_t)((128 * opacity + (uint32_t)U[i2] * (255 - opacity)) / 255); | 
				
			||||
                V[i2] = (uint8_t)((128 * opacity + (uint32_t)V[i2] * (255 - opacity)) / 255); | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
 | 
				
			||||
static int get_text_width(FT_Face face, const char *text) { | 
				
			||||
    int ret = 0; | 
				
			||||
 | 
				
			||||
    for (const char *ptr = text; *ptr != 0x00; ptr++) { | 
				
			||||
        int error = FT_Load_Char(face, *ptr, FT_LOAD_RENDER); | 
				
			||||
        if (error) { | 
				
			||||
            continue; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        ret += face->glyph->advance.x >> 6; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    return ret; | 
				
			||||
} | 
				
			||||
 | 
				
			||||
void text_draw(text_t *text, uint8_t *buf, int stride, int height) { | 
				
			||||
    text_priv_t *textp = (text_priv_t *)text; | 
				
			||||
 | 
				
			||||
    if (textp->enabled) { | 
				
			||||
        time_t timer = time(NULL); | 
				
			||||
        struct tm *tm_info = localtime(&timer); | 
				
			||||
        char buffer[255]; | 
				
			||||
        memset(buffer, 0, sizeof(buffer)); | 
				
			||||
        strftime(buffer, 255, textp->text_overlay, tm_info); | 
				
			||||
 | 
				
			||||
        draw_rect( | 
				
			||||
            buf, | 
				
			||||
            stride, | 
				
			||||
            height, | 
				
			||||
            7, | 
				
			||||
            7, | 
				
			||||
            get_text_width(textp->face, buffer) + 10, | 
				
			||||
            34); | 
				
			||||
 | 
				
			||||
        int x = 12; | 
				
			||||
        int y = 33; | 
				
			||||
 | 
				
			||||
        for (const char *ptr = buffer; *ptr != 0x00; ptr++) { | 
				
			||||
            int error = FT_Load_Char(textp->face, *ptr, FT_LOAD_RENDER); | 
				
			||||
            if (error) { | 
				
			||||
                continue; | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            draw_bitmap( | 
				
			||||
                buf, | 
				
			||||
                stride, | 
				
			||||
                height, | 
				
			||||
                &textp->face->glyph->bitmap, | 
				
			||||
                x + textp->face->glyph->bitmap_left, | 
				
			||||
                y - textp->face->glyph->bitmap_top); | 
				
			||||
 | 
				
			||||
            x += textp->face->glyph->advance.x >> 6; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,15 @@
				@@ -0,0 +1,15 @@
					 | 
				
			||||
#ifndef __TEXT_H__ | 
				
			||||
#define __TEXT_H__ | 
				
			||||
 | 
				
			||||
#include <stdint.h> | 
				
			||||
#include <stdbool.h> | 
				
			||||
 | 
				
			||||
#include "parameters.h" | 
				
			||||
 | 
				
			||||
typedef void text_t; | 
				
			||||
 | 
				
			||||
const char *text_get_error(); | 
				
			||||
bool text_create(const parameters_t *params, text_t **text); | 
				
			||||
void text_draw(text_t *text, uint8_t *buf, int stride, int height); | 
				
			||||
 | 
				
			||||
#endif | 
				
			||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						
					Loading…
					
					
				
		Reference in new issue