all repos — mgba @ 5a1ec94b02758b2fc4528572dda54ac0d648ef64

mGBA Game Boy Advance Emulator

src/platform/3ds/gui-font.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba-util/gui/font.h>
  7#include <mgba-util/gui/font-metrics.h>
  8#include <mgba-util/png-io.h>
  9#include <mgba-util/vfs.h>
 10#include "icons.h"
 11
 12#include "ctr-gpu.h"
 13
 14#define FONT_SIZE 15.6f
 15
 16struct GUIFont {
 17	CFNT_s* font;
 18	C3D_Tex* sheets;
 19	C3D_Tex icons;
 20	float size;
 21};
 22
 23struct GUIFont* GUIFontCreate(void) {
 24	fontEnsureMapped();
 25	struct GUIFont* guiFont = malloc(sizeof(struct GUIFont));
 26	if (!guiFont) {
 27		return 0;
 28	}
 29	C3D_Tex* tex;
 30
 31	guiFont->font = fontGetSystemFont();
 32	TGLP_s* glyphInfo = fontGetGlyphInfo(guiFont->font);
 33	guiFont->size = FONT_SIZE / glyphInfo->cellHeight;
 34	guiFont->sheets = calloc(glyphInfo->nSheets, sizeof(*guiFont->sheets));
 35
 36	int i;
 37	for (i = 0; i < glyphInfo->nSheets; ++i) {
 38		tex = &guiFont->sheets[i];
 39		tex->data = fontGetGlyphSheetTex(guiFont->font, i);
 40		tex->fmt = glyphInfo->sheetFmt;
 41		tex->size = glyphInfo->sheetSize;
 42		tex->width = glyphInfo->sheetWidth;
 43		tex->height = glyphInfo->sheetHeight;
 44		tex->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE);
 45	}
 46
 47	tex = &guiFont->icons;
 48	C3D_TexInitVRAM(tex, 256, 64, GPU_RGBA5551);
 49
 50	GSPGPU_FlushDataCache(icons, icons_size);
 51	GX_RequestDma((u32*) icons, tex->data, icons_size);
 52	gspWaitForDMA();
 53
 54	return guiFont;
 55}
 56
 57void GUIFontDestroy(struct GUIFont* font) {
 58	free(font->sheets);
 59	C3D_TexDelete(&font->icons);
 60	free(font);
 61}
 62
 63unsigned GUIFontHeight(const struct GUIFont* font) {
 64	return fontGetInfo(font->font)->lineFeed * font->size;
 65}
 66
 67unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) {
 68	int index = fontGlyphIndexFromCodePoint(font->font, glyph);
 69	charWidthInfo_s* info = fontGetCharWidthInfo(font->font, index);
 70	if (info) {
 71		return info->charWidth * font->size;
 72	}
 73	return 0;
 74}
 75
 76void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) {
 77	UNUSED(font);
 78	if (icon >= GUI_ICON_MAX) {
 79		if (w) {
 80			*w = 0;
 81		}
 82		if (h) {
 83			*h = 0;
 84		}
 85	} else {
 86		if (w) {
 87			*w = defaultIconMetrics[icon].width;
 88		}
 89		if (h) {
 90			*h = defaultIconMetrics[icon].height;
 91		}
 92	}
 93}
 94
 95void GUIFontDrawGlyph(const struct GUIFont* font, int glyph_x, int glyph_y, uint32_t color, uint32_t glyph) {
 96	int index = fontGlyphIndexFromCodePoint(font->font, glyph);
 97	fontGlyphPos_s data;
 98	fontCalcGlyphPos(&data, font->font, index, 0, 1.0, 1.0);
 99
100	C3D_Tex* tex = &font->sheets[data.sheetIndex];
101	ctrActivateTexture(tex);
102
103	float width = data.texcoord.right - data.texcoord.left;
104	float height = data.texcoord.top - data.texcoord.bottom;
105	u16 x = glyph_x;
106	u16 y = glyph_y + tex->height * height / 8;
107	u16 u = tex->width * data.texcoord.left;
108	u16 v = tex->height * data.texcoord.bottom;
109
110	ctrAddRectEx(color, x, y,
111	             tex->width * width * font->size, tex->height * height * -font->size,
112	             u, v, tex->width * width, tex->height * height, 0);
113}
114
115void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
116	ctrActivateTexture(&font->icons);
117
118	if (icon >= GUI_ICON_MAX) {
119		return;
120	}
121
122	struct GUIIconMetric metric = defaultIconMetrics[icon];
123	switch (align & GUI_ALIGN_HCENTER) {
124	case GUI_ALIGN_HCENTER:
125		x -= metric.width / 2;
126		break;
127	case GUI_ALIGN_RIGHT:
128		x -= metric.width;
129		break;
130	}
131	switch (align & GUI_ALIGN_VCENTER) {
132	case GUI_ALIGN_VCENTER:
133		y -= metric.height / 2;
134		break;
135	case GUI_ALIGN_BOTTOM:
136		y -= metric.height;
137		break;
138	}
139	switch (orient) {
140	case GUI_ORIENT_HMIRROR:
141		ctrAddRectEx(color, x + metric.width, y,
142		             -metric.width, metric.height,
143		             metric.x, metric.y,
144		             metric.width, metric.height, 0);
145		break;
146	case GUI_ORIENT_VMIRROR:
147		ctrAddRectEx(color, x, y + metric.height,
148		             metric.width, -metric.height,
149		             metric.x, metric.y,
150		             metric.width, metric.height, 0);
151		break;
152	case GUI_ORIENT_0:
153	default:
154		// TODO: Rotation
155		ctrAddRect(color, x, y, metric.x, metric.y, metric.width, metric.height);
156		break;
157	}
158}
159
160void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) {
161	ctrActivateTexture(&font->icons);
162
163	if (icon >= GUI_ICON_MAX) {
164		return;
165	}
166
167	struct GUIIconMetric metric = defaultIconMetrics[icon];
168	ctrAddRectEx(color, x, y,
169	             w ? w : metric.width,
170	             h ? h : metric.height,
171	             metric.x, metric.y,
172	             metric.width, metric.height, 0);
173}