all repos — mgba @ 1ea453e6d22e3dfcb7f0276e83b25c406c0b3464

mGBA Game Boy Advance Emulator

src/platform/wii/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 "icons.h"
  9#include "font.h"
 10
 11#include <malloc.h>
 12#include <ogc/tpl.h>
 13
 14#define GLYPH_HEIGHT 24
 15#define CELL_HEIGHT 32
 16#define CELL_WIDTH 32
 17
 18struct GUIFont {
 19	TPLFile tdf;
 20	TPLFile iconsTdf;
 21};
 22
 23struct GUIFont* GUIFontCreate(void) {
 24	struct GUIFont* guiFont = malloc(sizeof(struct GUIFont));
 25	if (!guiFont) {
 26		return 0;
 27	}
 28
 29	// libogc's TPL code modifies and frees this itself...
 30	void* fontTpl = memalign(32, font_size);
 31	if (!fontTpl) {
 32		free(guiFont);
 33		return 0;
 34	}
 35	memcpy(fontTpl, font, font_size);
 36	TPL_OpenTPLFromMemory(&guiFont->tdf, fontTpl, font_size);
 37
 38	void* iconsTpl = memalign(32, icons_size);
 39	if (!iconsTpl) {
 40		TPL_CloseTPLFile(&guiFont->tdf);
 41		free(guiFont);
 42		return 0;
 43	}
 44	memcpy(iconsTpl, icons, icons_size);
 45	TPL_OpenTPLFromMemory(&guiFont->iconsTdf, iconsTpl, icons_size);
 46	return guiFont;
 47}
 48
 49void GUIFontDestroy(struct GUIFont* font) {
 50	TPL_CloseTPLFile(&font->tdf);
 51	TPL_CloseTPLFile(&font->iconsTdf);
 52	free(font);
 53}
 54
 55unsigned GUIFontHeight(const struct GUIFont* font) {
 56	UNUSED(font);
 57	return GLYPH_HEIGHT;
 58}
 59
 60unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) {
 61	UNUSED(font);
 62	if (glyph > 0x7F) {
 63		glyph = '?';
 64	}
 65	return defaultFontMetrics[glyph].width * 2;
 66}
 67
 68void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) {
 69	UNUSED(font);
 70	if (icon >= GUI_ICON_MAX) {
 71		if (w) {
 72			*w = 0;
 73		}
 74		if (h) {
 75			*h = 0;
 76		}
 77	} else {
 78		if (w) {
 79			*w = defaultIconMetrics[icon].width * 2;
 80		}
 81		if (h) {
 82			*h = defaultIconMetrics[icon].height * 2;
 83		}
 84	}
 85}
 86
 87void GUIFontDrawGlyph(const struct GUIFont* font, int x, int y, uint32_t color, uint32_t glyph) {
 88	color = (color >> 24) | (color << 8);
 89	GXTexObj tex;
 90	// Grumble grumble, libogc is bad about const-correctness
 91	struct GUIFont* ncfont = font;
 92	TPL_GetTexture(&ncfont->tdf, 0, &tex);
 93	GX_LoadTexObj(&tex, GX_TEXMAP0);
 94
 95	GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
 96	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
 97	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
 98
 99	if (glyph > 0x7F) {
100		glyph = '?';
101	}
102	struct GUIFontGlyphMetric metric = defaultFontMetrics[glyph];
103	s16 tx = (glyph & 15) * CELL_WIDTH + metric.padding.left * 2;
104	s16 ty = (glyph >> 4) * CELL_HEIGHT + metric.padding.top * 2;
105	GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
106	GX_Position2s16(x, y - GLYPH_HEIGHT + metric.padding.top * 2);
107	GX_Color1u32(color);
108	GX_TexCoord2f32(tx / 512.f, ty / 256.f);
109
110	GX_Position2s16(x + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2, y - GLYPH_HEIGHT + metric.padding.top * 2);
111	GX_Color1u32(color);
112	GX_TexCoord2f32((tx + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2) / 512.f, ty / 256.f);
113
114	GX_Position2s16(x + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2, y - GLYPH_HEIGHT + CELL_HEIGHT - metric.padding.bottom * 2);
115	GX_Color1u32(color);
116	GX_TexCoord2f32((tx + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2) / 512.f, (ty + CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2) / 256.f);
117
118	GX_Position2s16(x, y - GLYPH_HEIGHT + CELL_HEIGHT - metric.padding.bottom * 2);
119	GX_Color1u32(color);
120	GX_TexCoord2f32(tx / 512.f, (ty + CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2) / 256.f);
121	GX_End();
122}
123
124void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
125	if (icon >= GUI_ICON_MAX) {
126		return;
127	}
128
129	color = (color >> 24) | (color << 8);
130	GXTexObj tex;
131
132	struct GUIFont* ncfont = font;
133	TPL_GetTexture(&ncfont->iconsTdf, 0, &tex);
134	GX_LoadTexObj(&tex, GX_TEXMAP0);
135
136	GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
137	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
138	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
139
140	struct GUIIconMetric metric = defaultIconMetrics[icon];
141	switch (align & GUI_ALIGN_HCENTER) {
142	case GUI_ALIGN_HCENTER:
143		x -= metric.width;
144		break;
145	case GUI_ALIGN_RIGHT:
146		x -= metric.width * 2;
147		break;
148	}
149	switch (align & GUI_ALIGN_VCENTER) {
150	case GUI_ALIGN_VCENTER:
151		y -= metric.height;
152		break;
153	case GUI_ALIGN_BOTTOM:
154		y -= metric.height * 2;
155		break;
156	}
157
158	float u[4];
159	float v[4];
160
161	switch (orient) {
162	case GUI_ORIENT_0:
163	default:
164		// TODO: Rotations
165		u[0] = u[3] = metric.x / 256.f;
166		u[1] = u[2] = (metric.x + metric.width) / 256.f;
167		v[0] = v[1] = (metric.y + metric.height) / 64.f;
168		v[2] = v[3] = metric.y / 64.f;
169		break;
170	case GUI_ORIENT_HMIRROR:
171		u[0] = u[3] = (metric.x + metric.width) / 256.f;
172		u[1] = u[2] = metric.x / 256.f;
173		v[0] = v[1] = (metric.y + metric.height) / 64.f;
174		v[2] = v[3] = metric.y / 64.f;
175		break;
176	case GUI_ORIENT_VMIRROR:
177		u[0] = u[3] = metric.x / 256.f;
178		u[1] = u[2] = (metric.x + metric.width) / 256.f;
179		v[0] = v[1] = metric.y / 64.f;
180		v[2] = v[3] = (metric.y + metric.height) / 64.f;
181		break;
182	}
183
184	GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
185	GX_Position2s16(x, y + metric.height * 2);
186	GX_Color1u32(color);
187	GX_TexCoord2f32(u[0], v[0]);
188
189	GX_Position2s16(x + metric.width * 2, y + metric.height * 2);
190	GX_Color1u32(color);
191	GX_TexCoord2f32(u[1], v[1]);
192
193	GX_Position2s16(x + metric.width * 2, y);
194	GX_Color1u32(color);
195	GX_TexCoord2f32(u[2], v[2]);
196
197	GX_Position2s16(x, y);
198	GX_Color1u32(color);
199	GX_TexCoord2f32(u[3], v[3]);
200	GX_End();
201}
202
203void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) {
204	if (icon >= GUI_ICON_MAX) {
205		return;
206	}
207
208	color = (color >> 24) | (color << 8);
209	GXTexObj tex;
210
211	struct GUIFont* ncfont = font;
212	TPL_GetTexture(&ncfont->iconsTdf, 0, &tex);
213	GX_LoadTexObj(&tex, GX_TEXMAP0);
214
215	GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
216	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
217	GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
218
219	struct GUIIconMetric metric = defaultIconMetrics[icon];
220
221	float u[4];
222	float v[4];
223
224	if (!h) {
225		h = metric.height * 2;
226	}
227	if (!w) {
228		w = metric.width * 2;
229	}
230
231	u[0] = u[3] = metric.x / 256.f;
232	u[1] = u[2] = (metric.x + metric.width) / 256.f;
233	v[0] = v[1] = (metric.y + metric.height) / 64.f;
234	v[2] = v[3] = metric.y / 64.f;
235
236	GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
237	GX_Position2s16(x, y + h);
238	GX_Color1u32(color);
239	GX_TexCoord2f32(u[0], v[0]);
240
241	GX_Position2s16(x + w, y + h);
242	GX_Color1u32(color);
243	GX_TexCoord2f32(u[1], v[1]);
244
245	GX_Position2s16(x + w, y);
246	GX_Color1u32(color);
247	GX_TexCoord2f32(u[2], v[2]);
248
249	GX_Position2s16(x, y);
250	GX_Color1u32(color);
251	GX_TexCoord2f32(u[3], v[3]);
252	GX_End();
253}