From 2a5513473dfedf948ad761d52820727f7f885bd7 Mon Sep 17 00:00:00 2001 From: Reuh Date: Sat, 22 Aug 2015 16:45:32 +0200 Subject: [PATCH] Support for special characters in gfx.text; added scrolling to the default shell; updated sftdlib. There is a known bug with different text size in sftdlib. --- libs/sftdlib/libsftd/include/bin_packing_2d.h | 36 +++++ libs/sftdlib/libsftd/include/int_htab.h | 34 +++++ libs/sftdlib/libsftd/include/texture_atlas.h | 36 +++++ libs/sftdlib/libsftd/source/bin_packing_2d.c | 86 ++++++++++++ libs/sftdlib/libsftd/source/int_htab.c | 124 ++++++++++++++++++ libs/sftdlib/libsftd/source/sftd.c | 105 +++++++++++---- libs/sftdlib/libsftd/source/texture_atlas.c | 86 ++++++++++++ sdcard/3ds/ctruLua/example.lua | 11 +- sdcard/3ds/ctruLua/main.lua | 25 +++- source/gfx.c | 12 +- 10 files changed, 516 insertions(+), 39 deletions(-) create mode 100644 libs/sftdlib/libsftd/include/bin_packing_2d.h create mode 100644 libs/sftdlib/libsftd/include/int_htab.h create mode 100644 libs/sftdlib/libsftd/include/texture_atlas.h create mode 100644 libs/sftdlib/libsftd/source/bin_packing_2d.c create mode 100644 libs/sftdlib/libsftd/source/int_htab.c create mode 100644 libs/sftdlib/libsftd/source/texture_atlas.c diff --git a/libs/sftdlib/libsftd/include/bin_packing_2d.h b/libs/sftdlib/libsftd/include/bin_packing_2d.h new file mode 100644 index 0000000..87f62fc --- /dev/null +++ b/libs/sftdlib/libsftd/include/bin_packing_2d.h @@ -0,0 +1,36 @@ +#ifndef BIN_PACKING_2D_H +#define BIN_PACKING_2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct bp2d_position { + int x, y; +} bp2d_position; + +typedef struct bp2d_size { + int w, h; +} bp2d_size; + +typedef struct bp2d_rectangle { + int x, y, w, h; +} bp2d_rectangle; + +typedef struct bp2d_node { + struct bp2d_node *left; + struct bp2d_node *right; + bp2d_rectangle rect; + int filled; +} bp2d_node; + +bp2d_node *bp2d_create(const bp2d_rectangle *rect); +void bp2d_free(bp2d_node *node); +// 1 success, 0 failure +int bp2d_insert(bp2d_node *node, const bp2d_size *in_size, bp2d_position *out_pos); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/sftdlib/libsftd/include/int_htab.h b/libs/sftdlib/libsftd/include/int_htab.h new file mode 100644 index 0000000..2104461 --- /dev/null +++ b/libs/sftdlib/libsftd/include/int_htab.h @@ -0,0 +1,34 @@ +#ifndef INT_HTAB_H +#define INT_HTAB_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define INT_HTAB_MAX_LOAD (70) // over 100 + +typedef struct int_htab_entry { + unsigned int key; + void *value; +} int_htab_entry; + +typedef struct int_htab { + size_t size; + size_t used; + int_htab_entry *entries; +} int_htab; + +int_htab *int_htab_create(size_t size); +void int_htab_free(int_htab *htab); +int int_htab_insert(int_htab *htab, unsigned int key, void *value); +void *int_htab_find(const int_htab *htab, unsigned int key); +int int_htab_erase(const int_htab *htab, unsigned int key); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/sftdlib/libsftd/include/texture_atlas.h b/libs/sftdlib/libsftd/include/texture_atlas.h new file mode 100644 index 0000000..e973939 --- /dev/null +++ b/libs/sftdlib/libsftd/include/texture_atlas.h @@ -0,0 +1,36 @@ +#ifndef TEXTURE_ATLAS_H +#define TEXTURE_ATLAS_H + +#include "sf2d.h" +#include "bin_packing_2d.h" +#include "int_htab.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct atlas_htab_entry { + bp2d_rectangle rect; + int bitmap_left; + int bitmap_top; + int advance_x; + int advance_y; +} atlas_htab_entry; + +typedef struct texture_atlas { + sf2d_texture *tex; + bp2d_node *bp_root; + int_htab *htab; +} texture_atlas; + +texture_atlas *texture_atlas_create(int width, int height, sf2d_texfmt format, sf2d_place place); +void texture_atlas_free(texture_atlas *atlas); +int texture_atlas_insert(texture_atlas *atlas, unsigned int character, const void *image, int width, int height, int bitmap_left, int bitmap_top, int advance_x, int advance_y); +int texture_atlas_exists(texture_atlas *atlas, unsigned int character); +void texture_atlas_get(texture_atlas *atlas, unsigned int character, bp2d_rectangle *rect, int *bitmap_left, int *bitmap_top, int *advance_x, int *advance_y); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/sftdlib/libsftd/source/bin_packing_2d.c b/libs/sftdlib/libsftd/source/bin_packing_2d.c new file mode 100644 index 0000000..5f61dee --- /dev/null +++ b/libs/sftdlib/libsftd/source/bin_packing_2d.c @@ -0,0 +1,86 @@ +#include +#include "bin_packing_2d.h" + +bp2d_node *bp2d_create(const bp2d_rectangle *rect) +{ + bp2d_node *node = malloc(sizeof(*node)); + if (!node) + return NULL; + + node->left = NULL; + node->right = NULL; + node->rect.x = rect->x; + node->rect.y = rect->y; + node->rect.w = rect->w; + node->rect.h = rect->h; + node->filled = 0; + + return node; +} + +void bp2d_free(bp2d_node *node) +{ + if (node->left) { + bp2d_free(node->left); + } + if (node->right) { + bp2d_free(node->right); + } + free(node); +} + +int bp2d_insert(bp2d_node *node, const bp2d_size *in_size, bp2d_position *out_pos) +{ + if (node->left != NULL || node->right != NULL) { + int ret = bp2d_insert(node->left, in_size, out_pos); + if (ret == 0) { + return bp2d_insert(node->right, in_size, out_pos); + } + return ret; + } else { + if (node->filled) + return 0; + + if (in_size->w > node->rect.w || in_size->h > node->rect.h) + return 0; + + if (in_size->w == node->rect.w && in_size->h == node->rect.h) { + out_pos->x = node->rect.x; + out_pos->y = node->rect.y; + node->filled = 1; + return 1; + } + + int dw = node->rect.w - in_size->w; + int dh = node->rect.h - in_size->h; + + bp2d_rectangle left_rect, right_rect; + + if (dw > dh) { + left_rect.x = node->rect.x; + left_rect.y = node->rect.y; + left_rect.w = in_size->w; + left_rect.h = node->rect.h; + + right_rect.x = node->rect.x + in_size->w; + right_rect.y = node->rect.y; + right_rect.w = node->rect.w - in_size->w; + right_rect.h = node->rect.h; + } else { + left_rect.x = node->rect.x; + left_rect.y = node->rect.y; + left_rect.w = node->rect.w; + left_rect.h = in_size->h; + + right_rect.x = node->rect.x; + right_rect.y = node->rect.y + in_size->h; + right_rect.w = node->rect.w; + right_rect.h = node->rect.h - in_size->h; + } + + node->left = bp2d_create(&left_rect); + node->right = bp2d_create(&right_rect); + + return bp2d_insert(node->left, in_size, out_pos); + } +} diff --git a/libs/sftdlib/libsftd/source/int_htab.c b/libs/sftdlib/libsftd/source/int_htab.c new file mode 100644 index 0000000..2e1a076 --- /dev/null +++ b/libs/sftdlib/libsftd/source/int_htab.c @@ -0,0 +1,124 @@ +#include +#include +#include "int_htab.h" + +static inline unsigned int FNV_1a(unsigned int key) +{ + unsigned char *bytes = (unsigned char *)&key; + unsigned int hash = 2166136261U; + hash = (16777619U * hash) ^ bytes[0]; + hash = (16777619U * hash) ^ bytes[1]; + hash = (16777619U * hash) ^ bytes[2]; + hash = (16777619U * hash) ^ bytes[3]; + return hash; +} + +int_htab *int_htab_create(size_t size) +{ + int_htab *htab = malloc(sizeof(*htab)); + if (!htab) + return NULL; + + htab->size = size; + htab->used = 0; + + htab->entries = malloc(htab->size * sizeof(*htab->entries)); + memset(htab->entries, 0, htab->size * sizeof(*htab->entries)); + + return htab; +} + +void int_htab_free(int_htab *htab) +{ + int i; + for (i = 0; i < htab->size; i++) { + if (htab->entries[i].value != NULL) + free(htab->entries[i].value); + } + free(htab); +} + +void int_htab_resize(int_htab *htab, unsigned int new_size) +{ + int i; + int_htab_entry *old_entries; + unsigned int old_size; + + old_entries = htab->entries; + old_size = htab->size; + + htab->size = new_size; + htab->used = 0; + htab->entries = malloc(new_size * sizeof(*htab->entries)); + memset(htab->entries, 0, new_size * sizeof(*htab->entries)); + + for (i = 0; i < old_size; i++) { + if (old_entries[i].value != NULL) { + int_htab_insert(htab, old_entries[i].key, old_entries[i].value); + } + } + + free(old_entries); +} + +int int_htab_insert(int_htab *htab, unsigned int key, void *value) +{ + if (value == NULL) + return 0; + + /* Calculate the current load factor */ + if (((htab->used + 1)*100)/htab->size > INT_HTAB_MAX_LOAD) { + int_htab_resize(htab, 2*htab->size); + } + + unsigned int mask = htab->size - 1; + unsigned int idx = FNV_1a(key) & mask; + + /* Open addressing, linear probing */ + while (htab->entries[idx].value != NULL) { + idx = (idx + 1) & mask; + } + + htab->entries[idx].key = key; + htab->entries[idx].value = value; + htab->used++; + + return 1; +} + +void *int_htab_find(const int_htab *htab, unsigned int key) +{ + unsigned int mask = htab->size - 1; + unsigned int idx = FNV_1a(key) & mask; + + /* Open addressing, linear probing */ + while (htab->entries[idx].key != key && htab->entries[idx].value != NULL) { + idx = (idx + 1) & mask; + } + + /* Found the key */ + if (htab->entries[idx].key == key) { + return htab->entries[idx].value; + } + + return NULL; +} + +int int_htab_erase(const int_htab *htab, unsigned int key) +{ + unsigned int mask = htab->size - 1; + unsigned int idx = FNV_1a(key) & mask; + + /* Open addressing, linear probing */ + while (htab->entries[idx].key != key && htab->entries[idx].value != NULL) { + idx = (idx + 1) & mask; + } + + /* Found the key */ + if (htab->entries[idx].key == key) { + htab->entries[idx].value = NULL; + return 1; + } + + return 0; +} diff --git a/libs/sftdlib/libsftd/source/sftd.c b/libs/sftdlib/libsftd/source/sftd.c index e68a623..0df867f 100644 --- a/libs/sftdlib/libsftd/source/sftd.c +++ b/libs/sftdlib/libsftd/source/sftd.c @@ -1,10 +1,15 @@ #include "sftd.h" +#include "texture_atlas.h" +#include "bin_packing_2d.h" #include #include #include #include FT_CACHE_H #include FT_FREETYPE_H +#define ATLAS_DEFAULT_W 512 +#define ATLAS_DEFAULT_H 512 + static int sftd_initialized = 0; static FT_Library ftlibrary; static FTC_Manager ftcmanager; @@ -25,6 +30,7 @@ struct sftd_font { }; FTC_CMapCache cmapcache; FTC_ImageCache imagecache; + texture_atlas *tex_atlas; }; static FT_Error ftc_face_requester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *face) @@ -106,6 +112,8 @@ sftd_font *sftd_load_font_file(const char *filename) FTC_ImageCache_New(ftcmanager, &font->imagecache); font->from = SFTD_LOAD_FROM_FILE; + font->tex_atlas = texture_atlas_create(ATLAS_DEFAULT_W, ATLAS_DEFAULT_H, + TEXFMT_RGBA8, SF2D_PLACE_RAM); return font; } @@ -120,6 +128,8 @@ sftd_font *sftd_load_font_mem(const void *buffer, unsigned int size) FTC_ImageCache_New(ftcmanager, &font->imagecache); font->from = SFTD_LOAD_FROM_MEM; + font->tex_atlas = texture_atlas_create(ATLAS_DEFAULT_W, ATLAS_DEFAULT_H, + TEXFMT_RGBA8, SF2D_PLACE_RAM); return font; } @@ -132,25 +142,40 @@ void sftd_free_font(sftd_font *font) if (font->from == SFTD_LOAD_FROM_FILE) { free(font->filename); } + texture_atlas_free(font->tex_atlas); free(font); } } -static void draw_bitmap(FT_Bitmap *bitmap, int x, int y, unsigned int color) +static int atlas_add_glyph(texture_atlas *atlas, unsigned int glyph_index, const FT_BitmapGlyph bitmap_glyph) { - //This is too ugly - sf2d_texture *tex = sf2d_create_texture(bitmap->width, bitmap->rows, GPU_RGBA8, SF2D_PLACE_TEMP); + const FT_Bitmap *bitmap = &bitmap_glyph->bitmap; + + unsigned int *buffer = malloc(bitmap->width * bitmap->rows * 4); + unsigned int w = bitmap->width; + unsigned int h = bitmap->rows; int j, k; - for (j = 0; j < bitmap->rows; j++) { - for (k = 0; k < bitmap->width; k++) { - ((u32 *)tex->data)[j*tex->pow2_w + k] = __builtin_bswap32((color & ~0xFF) | bitmap->buffer[j*bitmap->width + k]); + for (j = 0; j < h; j++) { + for (k = 0; k < w; k++) { + if (bitmap->pixel_mode == FT_PIXEL_MODE_MONO) { + buffer[j*w + k] = + (bitmap->buffer[j*bitmap->pitch + k/8] & (1 << (7 - k%8))) + ? 0xFF : 0; + } else { + buffer[j*w + k] = 0x00FFFFFF | (bitmap->buffer[j*bitmap->pitch + k] << 24); + } } } - sf2d_texture_tile32(tex); - sf2d_draw_texture(tex, x, y); - sf2d_free_texture(tex); + int ret = texture_atlas_insert(atlas, glyph_index, buffer, + bitmap->width, bitmap->rows, + bitmap_glyph->left, bitmap_glyph->top, + bitmap_glyph->root.advance.x, bitmap_glyph->root.advance.y); + + free(buffer); + + return ret; } void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const char *text) @@ -166,7 +191,7 @@ void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned FT_Bool use_kerning = FT_HAS_KERNING(face); FT_UInt glyph_index, previous = 0; int pen_x = x; - int pen_y = y; + int pen_y = y + size; FTC_ScalerRec scaler; scaler.face_id = face_id; @@ -185,16 +210,31 @@ void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned pen_x += delta.x >> 6; } - FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL); - if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { - FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; + if (!texture_atlas_exists(font->tex_atlas, glyph_index)) { + FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL); - draw_bitmap(&bitmap_glyph->bitmap, pen_x + bitmap_glyph->left + x, pen_y - bitmap_glyph->top + y, color); - - pen_x += bitmap_glyph->root.advance.x >> 16; - pen_y += bitmap_glyph->root.advance.y >> 16; + if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph)) { + continue; + } } + bp2d_rectangle rect; + int bitmap_left, bitmap_top; + int advance_x, advance_y; + + texture_atlas_get(font->tex_atlas, glyph_index, + &rect, &bitmap_left, &bitmap_top, + &advance_x, &advance_y); + + sf2d_draw_texture_part_blend(font->tex_atlas->tex, + pen_x + bitmap_left, + pen_y - bitmap_top, + rect.x, rect.y, rect.w, rect.h, + color); + + pen_x += advance_x >> 16; + pen_y += advance_y >> 16; + previous = glyph_index; text++; } @@ -223,7 +263,7 @@ void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned FT_Bool use_kerning = FT_HAS_KERNING(face); FT_UInt glyph_index, previous = 0; int pen_x = x; - int pen_y = y; + int pen_y = y + size; FTC_ScalerRec scaler; scaler.face_id = face_id; @@ -242,16 +282,31 @@ void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned pen_x += delta.x >> 6; } - FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL); - if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { - FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; + if (!texture_atlas_exists(font->tex_atlas, glyph_index)) { + FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL); - draw_bitmap(&bitmap_glyph->bitmap, pen_x + bitmap_glyph->left + x, pen_y - bitmap_glyph->top + y, color); - - pen_x += bitmap_glyph->root.advance.x >> 16; - pen_y += bitmap_glyph->root.advance.y >> 16; + if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph)) { + continue; + } } + bp2d_rectangle rect; + int bitmap_left, bitmap_top; + int advance_x, advance_y; + + texture_atlas_get(font->tex_atlas, glyph_index, + &rect, &bitmap_left, &bitmap_top, + &advance_x, &advance_y); + + sf2d_draw_texture_part_blend(font->tex_atlas->tex, + pen_x + bitmap_left, + pen_y - bitmap_top, + rect.x, rect.y, rect.w, rect.h, + color); + + pen_x += advance_x >> 16; + pen_y += advance_y >> 16; + previous = glyph_index; text++; } diff --git a/libs/sftdlib/libsftd/source/texture_atlas.c b/libs/sftdlib/libsftd/source/texture_atlas.c new file mode 100644 index 0000000..dc46fac --- /dev/null +++ b/libs/sftdlib/libsftd/source/texture_atlas.c @@ -0,0 +1,86 @@ +#include +#include +#include "texture_atlas.h" + +texture_atlas *texture_atlas_create(int width, int height, sf2d_texfmt format, sf2d_place place) +{ + texture_atlas *atlas = malloc(sizeof(*atlas)); + if (!atlas) + return NULL; + + bp2d_rectangle rect; + rect.x = 0; + rect.y = 0; + rect.w = width; + rect.h = height; + + atlas->tex = sf2d_create_texture(width, height, format, place); + sf2d_texture_tile32(atlas->tex); + + atlas->bp_root = bp2d_create(&rect); + atlas->htab = int_htab_create(256); + + return atlas; +} + +void texture_atlas_free(texture_atlas *atlas) +{ + sf2d_free_texture(atlas->tex); + bp2d_free(atlas->bp_root); + int_htab_free(atlas->htab); + free(atlas); +} + +int texture_atlas_insert(texture_atlas *atlas, unsigned int character, const void *image, int width, int height, int bitmap_left, int bitmap_top, int advance_x, int advance_y) +{ + bp2d_size size; + size.w = width; + size.h = height; + + bp2d_position pos; + if (bp2d_insert(atlas->bp_root, &size, &pos) == 0) + return 0; + + atlas_htab_entry *entry = malloc(sizeof(*entry)); + + entry->rect.x = pos.x; + entry->rect.y = pos.y; + entry->rect.w = width; + entry->rect.h = height; + entry->bitmap_left = bitmap_left; + entry->bitmap_top = bitmap_top; + entry->advance_x = advance_x; + entry->advance_y = advance_y; + + int_htab_insert(atlas->htab, character, entry); + + int i, j; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + sf2d_set_pixel(atlas->tex, pos.x + j, pos.y + i, *(unsigned int *)(image + (j + i*width)*4)); + } + } + + GSPGPU_FlushDataCache(NULL, atlas->tex->data, atlas->tex->data_size); + + return 1; +} + +int texture_atlas_exists(texture_atlas *atlas, unsigned int character) +{ + return int_htab_find(atlas->htab, character) != NULL; +} + +void texture_atlas_get(texture_atlas *atlas, unsigned int character, bp2d_rectangle *rect, int *bitmap_left, int *bitmap_top, int *advance_x, int *advance_y) +{ + atlas_htab_entry *entry = int_htab_find(atlas->htab, character); + + rect->x = entry->rect.x; + rect->y = entry->rect.y; + rect->w = entry->rect.w; + rect->h = entry->rect.h; + *bitmap_left = entry->bitmap_left; + *bitmap_top = entry->bitmap_top; + *advance_x = entry->advance_x; + *advance_y = entry->advance_y; +} diff --git a/sdcard/3ds/ctruLua/example.lua b/sdcard/3ds/ctruLua/example.lua index f5598bb..cd3f1ae 100644 --- a/sdcard/3ds/ctruLua/example.lua +++ b/sdcard/3ds/ctruLua/example.lua @@ -44,8 +44,7 @@ while ctr.run() do if keys.held.up then y = y - 1 end if keys.held.down then y = y + 1 end - if keys.held.r then dMul = dMul + 0.05 end - if keys.held.l then dMul = dMul - 0.05 end + dMul = hid.pos3d() gfx.startFrame(gfx.GFX_TOP, gfx.GFX_LEFT) @@ -61,10 +60,10 @@ while ctr.run() do gfx.startFrame(gfx.GFX_BOTTOM) - gfx.color.setDefault(0, 0, 0) - gfx.text(5, 7, "FPS: "..math.ceil(gfx.getFPS())) - gfx.text(5, 20, "Hello world, from Lua !", 20) - gfx.text(5, 30, "Time: "..os.date()) + gfx.color.setDefault(gfx.color.RGBA8(0, 0, 0)) + gfx.text(5, 5, "FPS: "..math.ceil(gfx.getFPS())) + gfx.text(5, 17, "Hello world, from Lua ! éàçù", 20, gfx.color.RGBA8(0, 0, 0)) + gfx.text(5, 50, "Time: "..os.date()) texture1:draw(240, 10, angle); diff --git a/sdcard/3ds/ctruLua/main.lua b/sdcard/3ds/ctruLua/main.lua index 557a2ff..b8dcee9 100644 --- a/sdcard/3ds/ctruLua/main.lua +++ b/sdcard/3ds/ctruLua/main.lua @@ -2,6 +2,7 @@ local ctr = require("ctr") local gfx = require("ctr.gfx") local sel = 1 +local scroll = 0 local curdir = "/" local files = ctr.fs.list(curdir) @@ -10,8 +11,13 @@ while ctr.run() do local keys = ctr.hid.keys() if keys.down.start then break end - if keys.down.down and sel < #files then sel = sel + 1 - elseif keys.down.up and sel > 1 then sel = sel - 1 end + if keys.down.down and sel < #files then + sel = sel + 1 + if sel > scroll + 14 then scroll = scroll + 1 end + elseif keys.down.up and sel > 1 then + sel = sel - 1 + if sel <= scroll then scroll = scroll - 1 end + end if keys.down.a then local f = files[sel] @@ -21,6 +27,7 @@ while ctr.run() do else curdir = curdir..f.name.."/" end sel = 1 + scroll = 0 files = ctr.fs.list(curdir) if curdir ~= "/" then @@ -29,20 +36,26 @@ while ctr.run() do else if f.name:match("%..+$") == ".lua" then dofile(curdir..f.name) + -- reset things the script could have changed + gfx.color.setDefault(0xFFFFFFFF) + gfx.color.setBackground(0x000000FF) end end end gfx.startFrame(gfx.GFX_TOP) - gfx.text(3, 9, curdir) + gfx.rectangle(0, 10+(sel-scroll)*15, gfx.TOP_WIDTH, 15, 0, gfx.color.RGBA8(0, 0, 200)) - for i,f in pairs(files) do + for i = scroll+1, scroll+14, 1 do + local f = files[i] + if not f then break end local name = f.isDirectory and "["..f.name.."]" or f.name.." ("..f.fileSize.."b)" - if not f.isHidden then gfx.text(5, 9+i*9, name) end + if not f.isHidden then gfx.text(5, 12+(i-scroll)*15, name) end end - gfx.text(0, 9+sel*9, ">") + gfx.rectangle(0, 0, gfx.TOP_WIDTH, 25, 0, gfx.color.RGBA8(200, 200, 200)) + gfx.text(3, 3, curdir, 13, gfx.color.RGBA8(0, 0, 0)) gfx.endFrame() diff --git a/source/gfx.c b/source/gfx.c index 69f74c6..9d171c8 100644 --- a/source/gfx.c +++ b/source/gfx.c @@ -1,3 +1,5 @@ +#include + #include #include @@ -105,13 +107,19 @@ static int gfx_circle(lua_State *L) { static int gfx_text(lua_State *L) { int x = luaL_checkinteger(L, 1); int y = luaL_checkinteger(L, 2); - const char *text = luaL_checkstring(L, 3); + size_t len; + const char *text = luaL_checklstring(L, 3, &len); int size = luaL_optinteger(L, 4, 9); u32 color = luaL_optinteger(L, 5, color_default); // todo : font selection - sftd_draw_text(font_default, x, y, color, size, text); + // Wide caracters support. (wchar = UTF32 on 3DS.) + wchar_t wtext[len]; + len = mbstowcs(wtext, text, len); + *(wtext+len) = 0x0; // text end + + sftd_draw_wtext(font_default, x, y, color, size, wtext); return 0; }