all repos — mgba @ a8a73720830e4f7681f320b913ef72941b1e358e

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