From b798818e99116f58ed4dd02ac994d1441fe92d0b Mon Sep 17 00:00:00 2001 From: Firew0lf Date: Sat, 16 Apr 2016 13:24:03 +0200 Subject: [PATCH] Fixed the ROMFS, Removed some fields in fs.list(), Updated sftdlib fs.list() now returns a table with tables containing the fields "name", "fileSize", and "isDirectory" --- libs/sftdlib/libsftd/include/sftd.h | 13 +- libs/sftdlib/libsftd/source/sftd.c | 134 +++++++++--------- libs/sftdlib/libsftd/source/texture_atlas.c | 1 + source/font.c | 2 +- source/fs.c | 142 +++++++++----------- 5 files changed, 149 insertions(+), 143 deletions(-) diff --git a/libs/sftdlib/libsftd/include/sftd.h b/libs/sftdlib/libsftd/include/sftd.h index 9e3facc..8702a04 100644 --- a/libs/sftdlib/libsftd/include/sftd.h +++ b/libs/sftdlib/libsftd/include/sftd.h @@ -110,9 +110,19 @@ void sftd_draw_wtextf(sftd_font *font, int x, int y, unsigned int color, unsigne * @param font the font used to calculate the width * @param size the font size * @param text a pointer to the text that will be used to calculate the length + * @return the width in pixels */ int sftd_get_text_width(sftd_font *font, unsigned int size, const char *text); +/** + * @brief Returns the width of the given wide text in pixels + * @param font the font used to calculate the width + * @param size the font size + * @param text a pointer to the wide text that will be used to calculate the length + * @return the width in pixels + */ +int sftd_get_wtext_width(sftd_font *font, unsigned int size, const wchar_t *text); + /** * @brief Draws text using a font. The text will wrap after the pixels specified in lineWidth. * @param font the font to use @@ -149,9 +159,6 @@ void sftd_calc_bounding_box(int *boundingWidth, int *boundingHeight, sftd_font * */ void sftd_draw_textf_wrap(sftd_font *font, int x, int y, unsigned int color, unsigned int size, unsigned int lineWidth, const char *text, ...); -// (ctruLua addition) Based on sftd_draw_wtext, returns the width of the text drawn. -int sftd_width_wtext(sftd_font *font, unsigned int size, const wchar_t *text); - #ifdef __cplusplus } #endif diff --git a/libs/sftdlib/libsftd/source/sftd.c b/libs/sftdlib/libsftd/source/sftd.c index d0adf24..6dca62f 100644 --- a/libs/sftdlib/libsftd/source/sftd.c +++ b/libs/sftdlib/libsftd/source/sftd.c @@ -227,6 +227,13 @@ void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; while (*text) { + if(*text == '\n') { + pen_x = x; + pen_y += size; + text++; + continue; + } + glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text); if (use_kerning && previous && glyph_index) { @@ -304,6 +311,13 @@ void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; while (*text) { + if(*text == '\n') { + pen_x = x; + pen_y += size; + text++; + continue; + } + glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text); if (use_kerning && previous && glyph_index) { @@ -417,6 +431,66 @@ int sftd_get_text_width(sftd_font *font, unsigned int size, const char *text) return pen_x; } +int sftd_get_wtext_width(sftd_font *font, unsigned int size, const wchar_t *text) +{ + FTC_FaceID face_id = (FTC_FaceID)font; + FT_Face face; + FTC_Manager_LookupFace(font->ftcmanager, face_id, &face); + + FT_Int charmap_index; + charmap_index = FT_Get_Charmap_Index(face->charmap); + + FT_Glyph glyph; + FT_Bool use_kerning = FT_HAS_KERNING(face); + FT_UInt glyph_index, previous = 0; + int pen_x = 0; + int pen_y = size; + + FTC_ScalerRec scaler; + scaler.face_id = face_id; + scaler.width = size; + scaler.height = size; + scaler.pixel = 1; + + FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; + + while (*text) { + glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text); + + if (use_kerning && previous && glyph_index) { + FT_Vector delta; + FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta); + pen_x += delta.x >> 6; + } + + if (!texture_atlas_exists(font->tex_atlas, glyph_index)) { + FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL); + + if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph, size)) { + continue; + } + } + + bp2d_rectangle rect; + int bitmap_left, bitmap_top; + int advance_x, advance_y; + int glyph_size; + + texture_atlas_get(font->tex_atlas, glyph_index, + &rect, &bitmap_left, &bitmap_top, + &advance_x, &advance_y, &glyph_size); + + const float draw_scale = size/(float)glyph_size; + + pen_x += (advance_x >> 16) * draw_scale; + pen_y += (advance_y >> 16) * draw_scale; + + previous = glyph_index; + text++; + } + return pen_x; +} + void sftd_draw_text_wrap(sftd_font *font, int x, int y, unsigned int color, unsigned int size, unsigned int lineWidth, const char *text) { FTC_FaceID face_id = (FTC_FaceID)font; @@ -610,63 +684,3 @@ void sftd_draw_textf_wrap(sftd_font *font, int x, int y, unsigned int color, uns sftd_draw_text_wrap(font, x, y, color, size, lineWidth, buffer); va_end(args); } - -// (ctruLua addition) Based on sftd_draw_wtext, returns the width of the text drawn. -int sftd_width_wtext(sftd_font *font, unsigned int size, const wchar_t *text) -{ - FTC_FaceID face_id = (FTC_FaceID)font; - FT_Face face; - FTC_Manager_LookupFace(font->ftcmanager, face_id, &face); - - FT_Int charmap_index; - charmap_index = FT_Get_Charmap_Index(face->charmap); - - FT_Glyph glyph; - FT_Bool use_kerning = FT_HAS_KERNING(face); - FT_UInt glyph_index, previous = 0; - int pen_x = 0; - - FTC_ScalerRec scaler; - scaler.face_id = face_id; - scaler.width = size; - scaler.height = size; - scaler.pixel = 1; - - FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; - - while (*text) { - glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text); - - if (use_kerning && previous && glyph_index) { - FT_Vector delta; - FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta); - pen_x += delta.x >> 6; - } - - if (!texture_atlas_exists(font->tex_atlas, glyph_index)) { - FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL); - - if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph, size)) { - continue; - } - } - - bp2d_rectangle rect; - int bitmap_left, bitmap_top; - int advance_x, advance_y; - int glyph_size; - - texture_atlas_get(font->tex_atlas, glyph_index, - &rect, &bitmap_left, &bitmap_top, - &advance_x, &advance_y, &glyph_size); - - const float draw_scale = size/(float)glyph_size; - - pen_x += (advance_x >> 16) * draw_scale; - - previous = glyph_index; - text++; - } - - return pen_x; -} diff --git a/libs/sftdlib/libsftd/source/texture_atlas.c b/libs/sftdlib/libsftd/source/texture_atlas.c index 03320c5..f8e76bc 100644 --- a/libs/sftdlib/libsftd/source/texture_atlas.c +++ b/libs/sftdlib/libsftd/source/texture_atlas.c @@ -15,6 +15,7 @@ texture_atlas *texture_atlas_create(int width, int height, sf2d_texfmt format, s rect.h = height; atlas->tex = sf2d_create_texture(width, height, format, place); + sf2d_texture_set_params(atlas->tex, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR)); sf2d_texture_tile32(atlas->tex); atlas->bp_root = bp2d_create(&rect); diff --git a/source/font.c b/source/font.c index 935aa64..80542c9 100644 --- a/source/font.c +++ b/source/font.c @@ -95,7 +95,7 @@ static int font_object_width(lua_State *L) { len = mbstowcs(wtext, text, len); *(wtext+len) = 0x0; // text end - lua_pushinteger(L, sftd_width_wtext(font->font, size, wtext)); + lua_pushinteger(L, sftd_get_wtext_width(font->font, size, wtext)); return 1; } diff --git a/source/fs.c b/source/fs.c index dd5faeb..54d67d6 100644 --- a/source/fs.c +++ b/source/fs.c @@ -3,25 +3,24 @@ The `fs` module. @module ctr.fs @usage local fs = require("ctr.fs") */ +#include #include #include #include +#include +#include #include <3ds/types.h> #include <3ds/util/utf.h> #include <3ds/services/fs.h> +#include <3ds/sdmc.h> +#include <3ds/romfs.h> #include #include bool isFsInitialized = false; -Handle *fsuHandle; -FS_Archive sdmcArchive; -#ifdef ROMFS -FS_Archive romfsArchive; -#endif - /*** The `ctr.fs.lzlib` module. @table lzlib @@ -57,81 +56,76 @@ Lists a directory contents (unsorted). ` { name = "Item name.txt", - shortName = "ITEM~", - shortExt = "TXT", isDirectory = false, - isHidden = false, - isArchive = false, - isReadOnly = false, fileSize = 321 -- (integer) in bytes } ` */ static int fs_list(lua_State *L) { - const char *path = prefix_path(luaL_checkstring(L, 1)); + const char* basepath = prefix_path(luaL_checkstring(L, 1)); + char* path; + bool shouldFreePath = false; + if (basepath[strlen(basepath)-1] != '/') { + path = malloc(strlen(basepath)+2); + strcpy(path, basepath); + strcat(path, "/"); + shouldFreePath = true; + } else { + path = (char*)basepath; + } lua_newtable(L); int i = 1; // table index - - // Get default archive - #ifdef ROMFS - FS_Archive archive = romfsArchive; - #else - FS_Archive archive = sdmcArchive; - #endif - // Archive path override (and skip path prefix) - if (strncmp(path, "sdmc:", 5) == 0) { - path += 5; - archive = sdmcArchive; - #ifdef ROMFS - } else if (strncmp(path, "romfs:", 6) == 0) { - path += 6; - archive = romfsArchive; - #endif + + DIR* dir = opendir(path); + if (dir == NULL) { + if (shouldFreePath) free(path); + lua_pushboolean(L, false); + lua_pushstring(L, strerror(errno)); + return 2; } - - FS_Path dirPath = fsMakePath(PATH_ASCII, path); - - Handle dirHandle; - FSUSER_OpenDirectory(&dirHandle, archive, dirPath); - - u32 entriesRead = 0; - do { - FS_DirectoryEntry buffer; - - FSDIR_Read(dirHandle, &entriesRead, 1, &buffer); - - if (!entriesRead) break; - - uint8_t name[0x106+1]; // utf8 file name - size_t size = utf16_to_utf8(name, buffer.name, 0x106); - *(name+size) = 0x0; // mark text end - - lua_createtable(L, 0, 8); - - lua_pushstring(L, (const char *)name); + errno = 0; + struct dirent *entry; + while (((entry = readdir(dir)) != NULL) && !errno) { + lua_createtable(L, 0, 3); + + lua_pushstring(L, (const char*)entry->d_name); lua_setfield(L, -2, "name"); - lua_pushstring(L, (const char *)buffer.shortName); - lua_setfield(L, -2, "shortName"); - lua_pushstring(L, (const char *)buffer.shortExt); - lua_setfield(L, -2, "shortExt"); - lua_pushboolean(L, buffer.attributes&FS_ATTRIBUTE_DIRECTORY); + lua_pushboolean(L, entry->d_type==DT_DIR); lua_setfield(L, -2, "isDirectory"); - lua_pushboolean(L, buffer.attributes&FS_ATTRIBUTE_HIDDEN); - lua_setfield(L, -2, "isHidden"); - lua_pushboolean(L, buffer.attributes&FS_ATTRIBUTE_ARCHIVE); - lua_setfield(L, -2, "isArchive"); - lua_pushboolean(L, buffer.attributes&FS_ATTRIBUTE_READ_ONLY); - lua_setfield(L, -2, "isReadOnly"); - lua_pushinteger(L, buffer.fileSize); + + if (entry->d_type==DT_REG) { // Regular files: check size + char* filepath = malloc(strlen(path)+strlen(entry->d_name)+1); + if (filepath == NULL) { + luaL_error(L, "Memory allocation error"); + } + memset(filepath, 0, strlen(path)+strlen(entry->d_name)+1); + + strcpy(filepath, path); + strcat(filepath, entry->d_name); + struct stat stats; + if (stat(filepath, &stats)) { + free(filepath); + if (shouldFreePath) free(path); + luaL_error(L, "Stat error: %s (%d)", strerror(errno), errno); + lua_pushboolean(L, false); + lua_pushstring(L, strerror(errno)); + return 2; + } else { + lua_pushinteger(L, stats.st_size); + } + free(filepath); + } else { // Everything else: 0 bytes + lua_pushinteger(L, 0); + } lua_setfield(L, -2, "fileSize"); lua_seti(L, -2, i); i++; - - } while (entriesRead > 0); - - FSDIR_Close(dirHandle); + } + + closedir(dir); + if (shouldFreePath) free(path); return 1; } @@ -214,16 +208,9 @@ int luaopen_fs_lib(lua_State *L) { void load_fs_lib(lua_State *L) { if (!isFsInitialized) { - fsInit(); - - fsuHandle = fsGetSessionHandle(); - FSUSER_Initialize(*fsuHandle); - - sdmcArchive = (FS_Archive){ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")}; - FSUSER_OpenArchive(&sdmcArchive); + sdmcInit(); #ifdef ROMFS - romfsArchive = (FS_Archive){ARCHIVE_ROMFS, fsMakePath(PATH_EMPTY, "")}; - FSUSER_OpenArchive(&romfsArchive); + romfsInit(); #endif isFsInitialized = true; } @@ -232,11 +219,8 @@ void load_fs_lib(lua_State *L) { } void unload_fs_lib(lua_State *L) { - FSUSER_CloseArchive(&sdmcArchive); + sdmcExit(); #ifdef ROMFS - FSUSER_CloseArchive(&romfsArchive); + romfsExit(); #endif - - fsExit(); } -