231 lines
4.9 KiB
C
Raw Normal View History

2016-08-01 00:43:38 +02:00
#include <psp2/pgf.h>
#include <psp2/kernel/sysmem.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <malloc.h>
#include <math.h>
#include "vita2d.h"
#include "texture_atlas.h"
#include "bin_packing_2d.h"
#include "utils.h"
#include "shared.h"
2016-08-23 02:49:53 +02:00
#define ATLAS_DEFAULT_W 512
#define ATLAS_DEFAULT_H 512
2016-08-01 00:43:38 +02:00
typedef struct vita2d_pgf {
SceFontLibHandle lib_handle;
SceFontHandle font_handle;
2016-08-23 02:49:53 +02:00
texture_atlas *atlas;
float vsize;
2016-08-01 00:43:38 +02:00
} vita2d_pgf;
static void *pgf_alloc_func(void *userdata, unsigned int size)
{
return memalign(sizeof(int), size + sizeof(int));
}
static void pgf_free_func(void *userdata, void *p)
{
free(p);
}
vita2d_pgf *vita2d_load_default_pgf()
{
unsigned int error;
2016-08-23 02:49:53 +02:00
SceFontInfo fontinfo;
2016-08-01 00:43:38 +02:00
vita2d_pgf *font = malloc(sizeof(*font));
if (!font)
return NULL;
SceFontNewLibParams params = {
font,
1,
NULL,
pgf_alloc_func,
pgf_free_func,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
font->lib_handle = sceFontNewLib(&params, &error);
if (error != 0) {
free(font);
return NULL;
}
2016-08-23 02:49:53 +02:00
font->font_handle = sceFontOpen(font->lib_handle, 0, 0, &error);
2016-08-01 00:43:38 +02:00
if (error != 0) {
sceFontDoneLib(font->lib_handle);
free(font);
return NULL;
}
2016-08-23 02:49:53 +02:00
sceFontGetFontInfo(font->font_handle, &fontinfo);
font->vsize = (fontinfo.fontStyle.fontV / fontinfo.fontStyle.fontVRes)
* SCREEN_DPI;
font->atlas = texture_atlas_create(ATLAS_DEFAULT_W, ATLAS_DEFAULT_H,
2016-08-01 00:43:38 +02:00
SCE_GXM_TEXTURE_FORMAT_U8_R111);
return font;
}
void vita2d_free_pgf(vita2d_pgf *font)
{
if (font) {
sceFontClose(font->font_handle);
sceFontDoneLib(font->lib_handle);
2016-08-23 02:49:53 +02:00
texture_atlas_free(font->atlas);
2016-08-01 00:43:38 +02:00
free(font);
}
}
2016-08-01 01:02:26 +02:00
static int atlas_add_glyph_pgf(vita2d_pgf *font, unsigned int character)
2016-08-01 00:43:38 +02:00
{
SceFontCharInfo char_info;
2016-08-23 02:49:53 +02:00
bp2d_position position;
void *texture_data;
vita2d_texture *tex = font->atlas->texture;
2016-08-01 00:43:38 +02:00
if (sceFontGetCharInfo(font->font_handle, character, &char_info) < 0)
return 0;
2016-08-23 02:49:53 +02:00
bp2d_size size = {
char_info.bitmapWidth,
char_info.bitmapHeight
};
texture_atlas_entry_data data = {
char_info.bitmapLeft,
char_info.bitmapTop,
2016-08-01 00:43:38 +02:00
char_info.sfp26AdvanceH,
char_info.sfp26AdvanceV,
2016-08-23 02:49:53 +02:00
0
};
if (!texture_atlas_insert(font->atlas, character, &size, &data,
&position))
2016-08-01 00:43:38 +02:00
return 0;
2016-08-23 02:49:53 +02:00
texture_data = vita2d_texture_get_datap(tex);
2016-08-01 00:43:38 +02:00
SceFontGlyphImage glyph_image;
glyph_image.pixelFormat = SCE_FONT_PIXELFORMAT_8;
2016-08-23 02:49:53 +02:00
glyph_image.xPos64 = position.x << 6;
glyph_image.yPos64 = position.y << 6;
2016-08-01 00:43:38 +02:00
glyph_image.bufWidth = vita2d_texture_get_width(tex);
glyph_image.bufHeight = vita2d_texture_get_height(tex);
glyph_image.bytesPerLine = vita2d_texture_get_stride(tex);
glyph_image.pad = 0;
2016-08-23 02:49:53 +02:00
glyph_image.bufferPtr = (unsigned int)texture_data;
2016-08-01 00:43:38 +02:00
return sceFontGetCharGlyphImage(font->font_handle, character, &glyph_image) == 0;
}
2016-08-23 02:49:53 +02:00
int generic_pgf_draw_text(vita2d_pgf *font, int draw, int *height,
int x, int y, unsigned int color, float scale,
const char *text)
2016-08-01 00:43:38 +02:00
{
2016-08-23 02:49:53 +02:00
unsigned int character;
bp2d_rectangle rect;
texture_atlas_entry_data data;
vita2d_texture *tex = font->atlas->texture;
int start_x = x;
int max_x = 0;
2016-08-01 00:43:38 +02:00
int pen_x = x;
2016-08-23 02:49:53 +02:00
int pen_y = y;
2016-08-01 00:43:38 +02:00
while (*text) {
2016-08-23 02:49:53 +02:00
character = utf8_character(&text);
if (character == '\n') {
if (pen_x > max_x)
max_x = pen_x;
pen_x = start_x;
pen_y += font->vsize * scale;
continue;
}
2016-08-01 00:43:38 +02:00
2016-08-23 02:49:53 +02:00
if (!texture_atlas_get(font->atlas, character, &rect, &data)) {
2016-08-01 01:02:26 +02:00
if (!atlas_add_glyph_pgf(font, character)) {
2016-08-01 00:43:38 +02:00
continue;
}
2016-08-23 02:49:53 +02:00
if (!texture_atlas_get(font->atlas, character,
&rect, &data))
continue;
2016-08-01 00:43:38 +02:00
}
2016-08-23 02:49:53 +02:00
if (draw) {
vita2d_draw_texture_tint_part_scale(tex,
pen_x + data.bitmap_left * scale,
pen_y - data.bitmap_top * scale,
rect.x, rect.y, rect.w, rect.h,
scale,
scale,
color);
}
2016-08-01 00:43:38 +02:00
2016-08-23 02:49:53 +02:00
pen_x += (data.advance_x >> 6) * scale;
}
2016-08-01 00:43:38 +02:00
2016-08-23 02:49:53 +02:00
if (pen_x > max_x)
max_x = pen_x;
2016-08-01 00:43:38 +02:00
2016-08-23 02:49:53 +02:00
if (height)
*height = pen_y + font->vsize * scale - y;
return max_x - x;
}
2016-08-01 00:43:38 +02:00
2016-08-23 02:49:53 +02:00
int vita2d_pgf_draw_text(vita2d_pgf *font, int x, int y,
unsigned int color, float scale,
const char *text)
{
return generic_pgf_draw_text(font, 1, NULL, x, y, color, scale, text);
2016-08-01 00:43:38 +02:00
}
2016-08-23 02:49:53 +02:00
int vita2d_pgf_draw_textf(vita2d_pgf *font, int x, int y,
unsigned int color, float scale,
const char *text, ...)
2016-08-01 00:43:38 +02:00
{
char buf[1024];
va_list argptr;
va_start(argptr, text);
vsnprintf(buf, sizeof(buf), text, argptr);
va_end(argptr);
return vita2d_pgf_draw_text(font, x, y, color, scale, buf);
}
2016-08-23 02:49:53 +02:00
void vita2d_pgf_text_dimensions(vita2d_pgf *font, float scale,
const char *text, int *width, int *height)
2016-08-01 00:43:38 +02:00
{
2016-08-23 02:49:53 +02:00
int w;
w = generic_pgf_draw_text(font, 0, height, 0, 0, 0, scale, text);
2016-08-01 00:43:38 +02:00
if (width)
2016-08-23 02:49:53 +02:00
*width = w;
2016-08-01 00:43:38 +02:00
}
int vita2d_pgf_text_width(vita2d_pgf *font, float scale, const char *text)
{
int width;
vita2d_pgf_text_dimensions(font, scale, text, &width, NULL);
return width;
}
int vita2d_pgf_text_height(vita2d_pgf *font, float scale, const char *text)
{
int height;
vita2d_pgf_text_dimensions(font, scale, text, NULL, &height);
return height;
}