all repos — mgba @ 0c748d3bfc6b8865a92307243101909ff79c3f4b

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 "util/gui/font.h"
  7#include "util/gui/font-metrics.h"
  8#include "util/png-io.h"
  9#include "util/vfs.h"
 10#include "icons.h"
 11
 12#include "ctr-gpu.h"
 13
 14#define CELL_HEIGHT 16
 15#define CELL_WIDTH 16
 16#define FONT_SIZE 0.52f
 17
 18struct GUIFont {
 19	C3D_Tex* sheets;
 20	C3D_Tex icons;
 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	TGLP_s* glyphInfo = fontGetGlyphInfo();
 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	UNUSED(font);
 63	return fontGetInfo()->lineFeed * FONT_SIZE;
 64}
 65
 66unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) {
 67	UNUSED(font);
 68	int index = fontGlyphIndexFromCodePoint(glyph);
 69	charWidthInfo_s* info = fontGetCharWidthInfo(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(glyph);
 97	fontGlyphPos_s data;
 98	fontCalcGlyphPos(&data, 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	ctrAddRectScaled(color, x, y, tex->width * width * FONT_SIZE, tex->height * height * -FONT_SIZE, u, v, tex->width * width, tex->height * height);
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		ctrAddRectScaled(color, x + metric.width, y, -metric.width, metric.height, metric.x, metric.y, metric.width, metric.height);
140		break;
141	case GUI_ORIENT_VMIRROR:
142		ctrAddRectScaled(color, x, y + metric.height, metric.width, -metric.height, metric.x, metric.y, metric.width, metric.height);
143		break;
144	case GUI_ORIENT_0:
145	default:
146		// TODO: Rotation
147		ctrAddRect(color, x, y, metric.x, metric.y, metric.width, metric.height);
148		break;
149	}
150}
151
152void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) {
153	ctrActivateTexture(&font->icons);
154
155	if (icon >= GUI_ICON_MAX) {
156		return;
157	}
158
159	struct GUIIconMetric metric = defaultIconMetrics[icon];
160	ctrAddRectScaled(color, x, y, w ? w : metric.width, h ? h : metric.height, metric.x, metric.y, metric.width, metric.height);
161}