all repos — mgba @ 0cace151e1148cfd12d4175f816a044871d8e113

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	C3D_Tex* sheets;
 18	C3D_Tex icons;
 19	float size;
 20};
 21
 22struct GUIFont* GUIFontCreate(void) {
 23	fontEnsureMapped();
 24	struct GUIFont* guiFont = malloc(sizeof(struct GUIFont));
 25	if (!guiFont) {
 26		return 0;
 27	}
 28	C3D_Tex* tex;
 29
 30	TGLP_s* glyphInfo = fontGetGlyphInfo();
 31	guiFont->size = FONT_SIZE / glyphInfo->cellHeight;
 32	guiFont->sheets = malloc(sizeof(*guiFont->sheets) * glyphInfo->nSheets);
 33
 34	int i;
 35	for (i = 0; i < glyphInfo->nSheets; ++i) {
 36		tex = &guiFont->sheets[i];
 37		tex->data = fontGetGlyphSheetTex(i);
 38		tex->fmt = glyphInfo->sheetFmt;
 39		tex->size = glyphInfo->sheetSize;
 40		tex->width = glyphInfo->sheetWidth;
 41		tex->height = glyphInfo->sheetHeight;
 42		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);
 43	}
 44
 45	tex = &guiFont->icons;
 46	C3D_TexInitVRAM(tex, 256, 64, GPU_RGBA5551);
 47
 48	GSPGPU_FlushDataCache(icons, icons_size);
 49	GX_RequestDma((u32*) icons, tex->data, icons_size);
 50	gspWaitForDMA();
 51
 52	return guiFont;
 53}
 54
 55void GUIFontDestroy(struct GUIFont* font) {
 56	free(font->sheets);
 57	C3D_TexDelete(&font->icons);
 58	free(font);
 59}
 60
 61unsigned GUIFontHeight(const struct GUIFont* font) {
 62	return fontGetInfo()->lineFeed * font->size;
 63}
 64
 65unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) {
 66	int index = fontGlyphIndexFromCodePoint(glyph);
 67	charWidthInfo_s* info = fontGetCharWidthInfo(index);
 68	if (info) {
 69		return info->charWidth * font->size;
 70	}
 71	return 0;
 72}
 73
 74void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) {
 75	UNUSED(font);
 76	if (icon >= GUI_ICON_MAX) {
 77		if (w) {
 78			*w = 0;
 79		}
 80		if (h) {
 81			*h = 0;
 82		}
 83	} else {
 84		if (w) {
 85			*w = defaultIconMetrics[icon].width;
 86		}
 87		if (h) {
 88			*h = defaultIconMetrics[icon].height;
 89		}
 90	}
 91}
 92
 93void GUIFontDrawGlyph(const struct GUIFont* font, int glyph_x, int glyph_y, uint32_t color, uint32_t glyph) {
 94	int index = fontGlyphIndexFromCodePoint(glyph);
 95	fontGlyphPos_s data;
 96	fontCalcGlyphPos(&data, index, 0, 1.0, 1.0);
 97
 98	C3D_Tex* tex = &font->sheets[data.sheetIndex];
 99	ctrActivateTexture(tex);
100
101	float width = data.texcoord.right - data.texcoord.left;
102	float height = data.texcoord.top - data.texcoord.bottom;
103	u16 x = glyph_x;
104	u16 y = glyph_y + tex->height * height / 8;
105	u16 u = tex->width * data.texcoord.left;
106	u16 v = tex->height * data.texcoord.bottom;
107
108	ctrAddRectEx(color, x, y,
109	             tex->width * width * font->size, tex->height * height * -font->size,
110	             u, v, tex->width * width, tex->height * height, 0);
111}
112
113void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
114	ctrActivateTexture(&font->icons);
115
116	if (icon >= GUI_ICON_MAX) {
117		return;
118	}
119
120	struct GUIIconMetric metric = defaultIconMetrics[icon];
121	switch (align & GUI_ALIGN_HCENTER) {
122	case GUI_ALIGN_HCENTER:
123		x -= metric.width / 2;
124		break;
125	case GUI_ALIGN_RIGHT:
126		x -= metric.width;
127		break;
128	}
129	switch (align & GUI_ALIGN_VCENTER) {
130	case GUI_ALIGN_VCENTER:
131		y -= metric.height / 2;
132		break;
133	case GUI_ALIGN_BOTTOM:
134		y -= metric.height;
135		break;
136	}
137	switch (orient) {
138	case GUI_ORIENT_HMIRROR:
139		ctrAddRectEx(color, x + metric.width, y,
140		             -metric.width, metric.height,
141		             metric.x, metric.y,
142		             metric.width, metric.height, 0);
143		break;
144	case GUI_ORIENT_VMIRROR:
145		ctrAddRectEx(color, x, y + metric.height,
146		             metric.width, -metric.height,
147		             metric.x, metric.y,
148		             metric.width, metric.height, 0);
149		break;
150	case GUI_ORIENT_0:
151	default:
152		// TODO: Rotation
153		ctrAddRect(color, x, y, metric.x, metric.y, metric.width, metric.height);
154		break;
155	}
156}
157
158void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) {
159	ctrActivateTexture(&font->icons);
160
161	if (icon >= GUI_ICON_MAX) {
162		return;
163	}
164
165	struct GUIIconMetric metric = defaultIconMetrics[icon];
166	ctrAddRectEx(color, x, y,
167	             w ? w : metric.width,
168	             h ? h : metric.height,
169	             metric.x, metric.y,
170	             metric.width, metric.height, 0);
171}