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 "ctr-gpu.h"
13
14#define FONT_SIZE 15.6f
15
16struct GUIFont {
17 CFNT_s* font;
18 C3D_Tex* sheets;
19 C3D_Tex icons;
20 float size;
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 guiFont->font = fontGetSystemFont();
32 TGLP_s* glyphInfo = fontGetGlyphInfo(guiFont->font);
33 guiFont->size = FONT_SIZE / glyphInfo->cellHeight;
34 guiFont->sheets = malloc(sizeof(*guiFont->sheets) * glyphInfo->nSheets);
35
36 int i;
37 for (i = 0; i < glyphInfo->nSheets; ++i) {
38 tex = &guiFont->sheets[i];
39 tex->data = fontGetGlyphSheetTex(guiFont->font, i);
40 tex->fmt = glyphInfo->sheetFmt;
41 tex->size = glyphInfo->sheetSize;
42 tex->width = glyphInfo->sheetWidth;
43 tex->height = glyphInfo->sheetHeight;
44 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);
45 }
46
47 tex = &guiFont->icons;
48 C3D_TexInitVRAM(tex, 256, 64, GPU_RGBA5551);
49
50 GSPGPU_FlushDataCache(icons, icons_size);
51 GX_RequestDma((u32*) icons, tex->data, icons_size);
52 gspWaitForDMA();
53
54 return guiFont;
55}
56
57void GUIFontDestroy(struct GUIFont* font) {
58 free(font->sheets);
59 C3D_TexDelete(&font->icons);
60 free(font);
61}
62
63unsigned GUIFontHeight(const struct GUIFont* font) {
64 return fontGetInfo(font->font)->lineFeed * font->size;
65}
66
67unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) {
68 int index = fontGlyphIndexFromCodePoint(font->font, glyph);
69 charWidthInfo_s* info = fontGetCharWidthInfo(font->font, 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(font->font, glyph);
97 fontGlyphPos_s data;
98 fontCalcGlyphPos(&data, font->font, 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}