Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Png support #95

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.dji
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ all: jni/*

install: all
install -d ipk/goggle/build/data/opt/fonts/
install fonts/*.bin ipk/goggle/build/data/opt/fonts/
install fonts/*.png ipk/goggle/build/data/opt/fonts/
install -d ipk/goggle/build/data/opt/mspdictionaries/
install dictionaries/*.bin ipk/goggle/build/data/opt/mspdictionaries/
install -d ipk/goggle/build/data/opt/etc/preload.d/
Expand Down
Binary file removed fonts/font.bin
Binary file not shown.
Binary file added fonts/font.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_2.bin
Binary file not shown.
Binary file removed fonts/font_ardu.bin
Binary file not shown.
Binary file added fonts/font_ardu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_ardu_2.bin
Binary file not shown.
Binary file removed fonts/font_ardu_hd.bin
Binary file not shown.
Binary file added fonts/font_ardu_hd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_ardu_hd_2.bin
Binary file not shown.
Binary file removed fonts/font_bf_hd.bin
Binary file not shown.
Binary file added fonts/font_bf_hd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_bf_hd_2.bin
Binary file not shown.
Binary file removed fonts/font_hd.bin
Binary file not shown.
Binary file added fonts/font_hd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_hd_2.bin
Binary file not shown.
Binary file removed fonts/font_inav.bin
Binary file not shown.
Binary file added fonts/font_inav.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_inav_2.bin
Binary file not shown.
Binary file removed fonts/font_inav_hd.bin
Binary file not shown.
Binary file added fonts/font_inav_hd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_inav_hd_2.bin
Binary file not shown.
Binary file removed fonts/font_ultra.bin
Binary file not shown.
Binary file added fonts/font_ultra.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_ultra_2.bin
Binary file not shown.
Binary file removed fonts/font_ultra_hd.bin
Binary file not shown.
Binary file added fonts/font_ultra_hd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed fonts/font_ultra_hd_2.bin
Binary file not shown.
6 changes: 4 additions & 2 deletions jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ include $(CLEAR_VARS)

LOCAL_CFLAGS += -fPIC -std=c99 -O3
LOCAL_LDFLAGS += -fPIC
LOCAL_LDLIBS := -llog
LOCAL_LDLIBS := -llog -lz
LOCAL_ARM_NEON := true
LOCAL_MODULE := displayport_osd_shim
LOCAL_SHARED_LIBRARIES := duml_hal
LOCAL_SRC_FILES := \
displayport_osd_shim.c \
fakehd/fakehd.c \
font/font.c \
hw/dji_display.c \
hw/dji_radio_shm.c \
hw/dji_services.c \
Expand All @@ -29,7 +30,8 @@ LOCAL_SRC_FILES := \
rec/rec.c \
util/fs_util.c \
toast/toast.c \
lz4/lz4.c
lz4/lz4.c \
libspng/spng.c
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
Expand Down
284 changes: 284 additions & 0 deletions jni/font/font.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "../libspng/spng.h"
#include "font.h"

#define BYTES_PER_PIXEL 4
#define HD_FONT_WIDTH 24

#ifdef DEBUG
#define DEBUG_PRINT(fmt, args...) fprintf(stderr, fmt, ## args)
#else
#define DEBUG_PRINT(fmt, args...)
#endif

/* Font helper methods */

font_variant_e font_variant_from_string(char *variant_string) {
font_variant_e font_variant = FONT_VARIANT_GENERIC;
if(strncmp(variant_string, "ARDU", 4) == 0) {
font_variant = FONT_VARIANT_ARDUPILOT;
} else if (strncmp(variant_string, "BTFL", 4) == 0) {
font_variant = FONT_VARIANT_BETAFLIGHT;
} else if (strncmp(variant_string, "INAV", 4) == 0) {
font_variant = FONT_VARIANT_INAV;
} else if (strncmp(variant_string, "ULTR", 4) == 0) {
font_variant = FONT_VARIANT_KISS_ULTRA;
}
return font_variant;
}

void get_font_path_with_extension(char *font_path_dest, const char *font_path, const char *extension, uint8_t len, uint8_t is_hd, font_variant_e font_variant)
{
char name_buf[len];
char res_buf[len];

switch (font_variant)
{
case FONT_VARIANT_BETAFLIGHT:
snprintf(name_buf, len, "%s_bf", font_path);
break;
case FONT_VARIANT_INAV:
snprintf(name_buf, len, "%s_inav", font_path);
break;
case FONT_VARIANT_ARDUPILOT:
snprintf(name_buf, len, "%s_ardu", font_path);
break;
case FONT_VARIANT_KISS_ULTRA:
snprintf(name_buf, len, "%s_ultra", font_path);
break;
default:
snprintf(name_buf, len, "%s", font_path);
}

if (is_hd)
{
// surely there's a better way...
snprintf(res_buf, len, "%s", "_hd");
} else {
snprintf(res_buf, len, "%s", "");
}
snprintf(font_path_dest, len, "%s%s%s", name_buf, res_buf, extension);
}

static int open_font(const char *filename, display_info_t *display_info, font_variant_e font_variant)
{
char file_path[255];
int is_hd = (display_info->char_width == HD_FONT_WIDTH) ? 1 : 0;
get_font_path_with_extension(file_path, filename, ".png", 255, is_hd, font_variant);
DEBUG_PRINT("Opening font: %s\n", file_path);
struct stat st;
memset(&st, 0, sizeof(st));
stat(file_path, &st);
size_t filesize = st.st_size;
if(!(filesize > 0)) {
DEBUG_PRINT("Font file did not exist: %s\n", file_path);
return -1;
}

FILE *fd = fopen(file_path, "rb");
if (!fd) {
DEBUG_PRINT("Could not open file %s\n", file_path);
return -1;
}

spng_ctx *ctx = spng_ctx_new(0);
DEBUG_PRINT("Allocated PNG context\n");
// Set some kind of reasonable PNG limit so we don't get blown up
size_t limit = 1024 * 1024 * 64;
spng_set_chunk_limits(ctx, limit, limit);
DEBUG_PRINT("Set PNG chunk limits\n");
spng_set_png_file(ctx, fd);
DEBUG_PRINT("Set PNG file\n");

struct spng_ihdr ihdr;
int ret = spng_get_ihdr(ctx, &ihdr);
DEBUG_PRINT("Got PNG header\n");

if(ret)
{
printf("spng_get_ihdr() error: %s\n", spng_strerror(ret));
goto err;
}

if(ihdr.height != display_info->font_height * NUM_CHARS) {
printf("font invalid height, got %d wanted %d\n", ihdr.height, display_info->font_height * NUM_CHARS);
goto err;
}

if(ihdr.width % display_info->font_width != 0) {
printf("font invalid width, not a multiple of %d\n", display_info->font_width);
goto err;
}

DEBUG_PRINT("Image pixel size %d x %d\n", ihdr.width, ihdr.height);

int num_pages = ihdr.width / display_info->font_width;

DEBUG_PRINT("Font has %d pages\n", num_pages);

size_t image_size = 0;
int fmt = SPNG_FMT_RGBA8;
ret = spng_decoded_image_size(ctx, fmt, &image_size);
if(ret) {
goto err;
}

DEBUG_PRINT("Allocating image size %d\n", image_size);

void* font_data = malloc(image_size);
ret = spng_decode_image(ctx, font_data, image_size, SPNG_FMT_RGBA8, 0);
if(ret) {
printf("Failed to decode PNG!\n");
free(font_data);
goto err;
}

for(int page = 0; page < num_pages; page++) {
DEBUG_PRINT("Loading font page %d of %d, placing %x\n", page, num_pages, display_info->fonts);
display_info->fonts[page] = malloc(display_info->font_width * display_info->font_height * NUM_CHARS * BYTES_PER_PIXEL);
DEBUG_PRINT("Allocated %d bytes for font page buf at%x\n", display_info->font_width * display_info->font_height * NUM_CHARS * BYTES_PER_PIXEL, display_info->fonts[page]);
for(int char_num = 0; char_num < NUM_CHARS; char_num++) {
for(int y = 0; y < display_info->font_height; y++) {
// Copy each character line at a time into the correct font buffer
int char_width_bytes = display_info->font_width * BYTES_PER_PIXEL;
int char_size_bytes_dest = (display_info->font_width * display_info->font_height * BYTES_PER_PIXEL);
int char_size_bytes_src = (ihdr.width * display_info->font_height * BYTES_PER_PIXEL);
memcpy((uint8_t *)display_info->fonts[page] + (char_num * char_size_bytes_dest) + (y * char_width_bytes), (uint8_t *)font_data + (char_num * char_size_bytes_src) + (ihdr.width * y * BYTES_PER_PIXEL) + (page * char_width_bytes), char_width_bytes);
}
}
}

free(font_data);
spng_ctx_free(ctx);
fclose(fd);
return 0;
err:
spng_ctx_free(ctx);
fclose(fd);
return -1;
}

void load_font(display_info_t *display_info, font_variant_e font_variant) {
// Note: load_font will not replace an existing font.
if(display_info->fonts[0] == NULL) {
if (open_font(SDCARD_FONT_PATH, display_info, font_variant) < 0) {
if (open_font(ENTWARE_FONT_PATH, display_info, font_variant) < 0) {
open_font(FALLBACK_FONT_PATH, display_info, font_variant);
}
}
}
}

void close_font(display_info_t *display_info) {
for(int i = 0; i < NUM_FONT_PAGES; i++) {
if(display_info->fonts[i] != NULL) {
free(display_info->fonts[i]);
display_info->fonts[i] = NULL;
}
}
}

void convert_bin_fonts(const char *file_location)
{
display_info_t sd_display_info = {
.char_width = 30,
.char_height = 15,
.font_width = 36,
.font_height = 54,
.x_offset = 180,
.y_offset = 0,
.fonts = {NULL, NULL, NULL, NULL},
};

static display_info_t hd_display_info = {
.char_width = 50,
.char_height = 18,
.font_width = 24,
.font_height = 36,
.x_offset = 120,
.y_offset = 80,
.fonts = {NULL, NULL, NULL, NULL},
};

for(int is_hd = 0; is_hd < 2; is_hd++) {
for(int i = 0; i < FONT_VARIANT_COUNT; i++) {
int page_count = 1;
char file_path[255];
get_font_path_with_extension(file_path, file_location, ".bin", 255, is_hd, i);
char page_2_file_path[255];
get_font_path_with_extension(page_2_file_path, file_location, "_2.bin", 255, is_hd, i);
char *file_paths[2] = {file_path, page_2_file_path};
struct stat st;
memset(&st, 0, sizeof(st));
stat(file_path, &st);
size_t page_1_filesize = st.st_size;
stat(page_2_file_path, &st);
size_t page_2_filesize = st.st_size;
display_info_t display_info = is_hd ? hd_display_info : sd_display_info;
size_t desired_filesize = display_info.font_height * display_info.font_width * NUM_CHARS * BYTES_PER_PIXEL;
DEBUG_PRINT("Found a font candidate to convert: %s %d\n", file_path, page_1_filesize);
if(page_1_filesize == desired_filesize) {
DEBUG_PRINT("Found a font to convert: %s %d\n", file_path, desired_filesize);
} else {
continue;
}
if(page_2_filesize == desired_filesize) {
page_count = 2;
}
void *image_buf = malloc(desired_filesize * page_count);
for(int page = 0; page < page_count; page++) {
int fd = open(file_paths[page], O_RDONLY, 0);
if (!fd) {
DEBUG_PRINT("Could not open file %s\n", file_path);
continue;
}
void* mmappedData = mmap(NULL, desired_filesize, PROT_READ, MAP_PRIVATE, fd, 0);
if (mmappedData != MAP_FAILED) {
for(int char_num = 0; char_num < NUM_CHARS; char_num++) {
for(int y = 0; y < display_info.font_height; y++) {
// Copy each character line at a time into the correct font buffer
int char_width_bytes = display_info.font_width * BYTES_PER_PIXEL;
int char_size_bytes_src = (display_info.font_width * display_info.font_height * BYTES_PER_PIXEL);
int char_size_bytes_dest = (display_info.font_width * page_count * display_info.font_height * BYTES_PER_PIXEL);
memcpy((uint8_t *)image_buf + (char_num * char_size_bytes_dest) + (display_info.font_width * page_count * y * BYTES_PER_PIXEL) + (page * char_width_bytes), (uint8_t *)mmappedData + (char_num * char_size_bytes_src) + (y * char_width_bytes), char_width_bytes);
}
}
} else {
DEBUG_PRINT("Could not map font %s\n", file_path);
free(image_buf);
continue;
}
close(fd);
munmap(mmappedData, desired_filesize);
}
char out_file_path[255];
get_font_path_with_extension(out_file_path, file_location, ".png", 255, is_hd, i);
FILE* out_fd = fopen(out_file_path, "wb");
if(out_fd == NULL) {
DEBUG_PRINT("Could not open output %s\n", out_file_path);
continue;
}
spng_ctx *enc = spng_ctx_new(SPNG_CTX_ENCODER);
struct spng_ihdr ihdr =
{
.width = display_info.font_width * page_count,
.height = display_info.font_height * NUM_CHARS,
.bit_depth = 8,
.color_type = SPNG_COLOR_TYPE_TRUECOLOR_ALPHA
};
spng_set_ihdr(enc, &ihdr);
spng_set_png_file(enc, out_fd);
spng_encode_image(enc, image_buf, desired_filesize * page_count, SPNG_FMT_PNG, SPNG_ENCODE_FINALIZE);
spng_ctx_free(enc);
free(image_buf);
fclose(out_fd);
}
}
}

22 changes: 22 additions & 0 deletions jni/font/font.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <stdint.h>

#include "../util/display_info.h"

#define FALLBACK_FONT_PATH "/blackbox/font"
#define ENTWARE_FONT_PATH "/opt/fonts/font"
#define SDCARD_FONT_PATH "/storage/sdcard0/font"

typedef enum {
FONT_VARIANT_GENERIC,
FONT_VARIANT_BETAFLIGHT,
FONT_VARIANT_INAV,
FONT_VARIANT_ARDUPILOT,
FONT_VARIANT_KISS_ULTRA,
FONT_VARIANT_COUNT
} font_variant_e;

void convert_bin_fonts(const char *file_location);
void load_font(display_info_t *display_info, font_variant_e font_variant);
void close_font(display_info_t *display_info);
void get_font_path_with_extension(char *font_path_dest, const char *font_path, const char *extension, uint8_t len, uint8_t is_hd, font_variant_e font_variant);
font_variant_e font_variant_from_string(char *variant_string);
Loading