mirror of
https://github.com/ctruLua/ctruLua.git
synced 2025-10-27 16:39:29 +00:00
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.
This commit is contained in:
parent
56b47153b7
commit
2a5513473d
10 changed files with 516 additions and 39 deletions
36
libs/sftdlib/libsftd/include/bin_packing_2d.h
Normal file
36
libs/sftdlib/libsftd/include/bin_packing_2d.h
Normal file
|
|
@ -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
|
||||
34
libs/sftdlib/libsftd/include/int_htab.h
Normal file
34
libs/sftdlib/libsftd/include/int_htab.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef INT_HTAB_H
|
||||
#define INT_HTAB_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#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
|
||||
36
libs/sftdlib/libsftd/include/texture_atlas.h
Normal file
36
libs/sftdlib/libsftd/include/texture_atlas.h
Normal file
|
|
@ -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
|
||||
86
libs/sftdlib/libsftd/source/bin_packing_2d.c
Normal file
86
libs/sftdlib/libsftd/source/bin_packing_2d.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#include <stdlib.h>
|
||||
#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);
|
||||
}
|
||||
}
|
||||
124
libs/sftdlib/libsftd/source/int_htab.c
Normal file
124
libs/sftdlib/libsftd/source/int_htab.c
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -1,10 +1,15 @@
|
|||
#include "sftd.h"
|
||||
#include "texture_atlas.h"
|
||||
#include "bin_packing_2d.h"
|
||||
#include <wchar.h>
|
||||
#include <sf2d.h>
|
||||
#include <ft2build.h>
|
||||
#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++;
|
||||
}
|
||||
|
|
|
|||
86
libs/sftdlib/libsftd/source/texture_atlas.c
Normal file
86
libs/sftdlib/libsftd/source/texture_atlas.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
12
source/gfx.c
12
source/gfx.c
|
|
@ -1,3 +1,5 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include <sf2d.h>
|
||||
#include <sftd.h>
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue