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