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 C3D_Tex* sheets;
18 C3D_Tex icons;
19 float size;
20};
21
22struct GUIFont* GUIFontCreate(void) {
23 fontEnsureMapped();
24 struct GUIFont* guiFont = malloc(sizeof(struct GUIFont));
25 if (!guiFont) {
26 return 0;
27 }
28 C3D_Tex* tex;
29
30 TGLP_s* glyphInfo = fontGetGlyphInfo();
31 guiFont->size = FONT_SIZE / glyphInfo->cellHeight;
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 return fontGetInfo()->lineFeed * font->size;
63}
64
65unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) {
66 int index = fontGlyphIndexFromCodePoint(glyph);
67 charWidthInfo_s* info = fontGetCharWidthInfo(index);
68 if (info) {
69 return info->charWidth * font->size;
70 }
71 return 0;
72}
73
74void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) {
75 UNUSED(font);
76 if (icon >= GUI_ICON_MAX) {
77 if (w) {
78 *w = 0;
79 }
80 if (h) {
81 *h = 0;
82 }
83 } else {
84 if (w) {
85 *w = defaultIconMetrics[icon].width;
86 }
87 if (h) {
88 *h = defaultIconMetrics[icon].height;
89 }
90 }
91}
92
93void GUIFontDrawGlyph(const struct GUIFont* font, int glyph_x, int glyph_y, uint32_t color, uint32_t glyph) {
94 int index = fontGlyphIndexFromCodePoint(glyph);
95 fontGlyphPos_s data;
96 fontCalcGlyphPos(&data, index, 0, 1.0, 1.0);
97
98 C3D_Tex* tex = &font->sheets[data.sheetIndex];
99 ctrActivateTexture(tex);
100
101 float width = data.texcoord.right - data.texcoord.left;
102 float height = data.texcoord.top - data.texcoord.bottom;
103 u16 x = glyph_x;
104 u16 y = glyph_y + tex->height * height / 8;
105 u16 u = tex->width * data.texcoord.left;
106 u16 v = tex->height * data.texcoord.bottom;
107
108 ctrAddRectEx(color, x, y,
109 tex->width * width * font->size, tex->height * height * -font->size,
110 u, v, tex->width * width, tex->height * height, 0);
111}
112
113void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
114 ctrActivateTexture(&font->icons);
115
116 if (icon >= GUI_ICON_MAX) {
117 return;
118 }
119
120 struct GUIIconMetric metric = defaultIconMetrics[icon];
121 switch (align & GUI_ALIGN_HCENTER) {
122 case GUI_ALIGN_HCENTER:
123 x -= metric.width / 2;
124 break;
125 case GUI_ALIGN_RIGHT:
126 x -= metric.width;
127 break;
128 }
129 switch (align & GUI_ALIGN_VCENTER) {
130 case GUI_ALIGN_VCENTER:
131 y -= metric.height / 2;
132 break;
133 case GUI_ALIGN_BOTTOM:
134 y -= metric.height;
135 break;
136 }
137 switch (orient) {
138 case GUI_ORIENT_HMIRROR:
139 ctrAddRectEx(color, x + metric.width, y,
140 -metric.width, metric.height,
141 metric.x, metric.y,
142 metric.width, metric.height, 0);
143 break;
144 case GUI_ORIENT_VMIRROR:
145 ctrAddRectEx(color, x, y + metric.height,
146 metric.width, -metric.height,
147 metric.x, metric.y,
148 metric.width, metric.height, 0);
149 break;
150 case GUI_ORIENT_0:
151 default:
152 // TODO: Rotation
153 ctrAddRect(color, x, y, metric.x, metric.y, metric.width, metric.height);
154 break;
155 }
156}
157
158void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) {
159 ctrActivateTexture(&font->icons);
160
161 if (icon >= GUI_ICON_MAX) {
162 return;
163 }
164
165 struct GUIIconMetric metric = defaultIconMetrics[icon];
166 ctrAddRectEx(color, x, y,
167 w ? w : metric.width,
168 h ? h : metric.height,
169 metric.x, metric.y,
170 metric.width, metric.height, 0);
171}