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}