all repos — mgba @ 6d898542c765f4efc4a094c5ebd3f3465c36f417

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	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}