src/platform/wii/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 "util/gui/font.h"
7#include "util/gui/font-metrics.h"
8#include "icons.h"
9#include "font.h"
10
11#include <malloc.h>
12#include <ogc/tpl.h>
13
14#define GLYPH_HEIGHT 24
15#define CELL_HEIGHT 32
16#define CELL_WIDTH 32
17
18struct GUIFont {
19 TPLFile tdf;
20 TPLFile iconsTdf;
21};
22
23struct GUIFont* GUIFontCreate(void) {
24 struct GUIFont* guiFont = malloc(sizeof(struct GUIFont));
25 if (!guiFont) {
26 return 0;
27 }
28
29 // libogc's TPL code modifies and frees this itself...
30 void* fontTpl = memalign(32, font_size);
31 if (!fontTpl) {
32 free(guiFont);
33 return 0;
34 }
35 memcpy(fontTpl, font, font_size);
36 TPL_OpenTPLFromMemory(&guiFont->tdf, fontTpl, font_size);
37
38 void* iconsTpl = memalign(32, icons_size);
39 if (!iconsTpl) {
40 TPL_CloseTPLFile(&guiFont->tdf);
41 free(guiFont);
42 return 0;
43 }
44 memcpy(iconsTpl, icons, icons_size);
45 TPL_OpenTPLFromMemory(&guiFont->iconsTdf, iconsTpl, icons_size);
46 return guiFont;
47}
48
49void GUIFontDestroy(struct GUIFont* font) {
50 TPL_CloseTPLFile(&font->tdf);
51 TPL_CloseTPLFile(&font->iconsTdf);
52 free(font);
53}
54
55unsigned GUIFontHeight(const struct GUIFont* font) {
56 UNUSED(font);
57 return GLYPH_HEIGHT;
58}
59
60unsigned GUIFontGlyphWidth(const struct GUIFont* font, uint32_t glyph) {
61 UNUSED(font);
62 if (glyph > 0x7F) {
63 glyph = '?';
64 }
65 return defaultFontMetrics[glyph].width * 2;
66}
67
68void GUIFontIconMetrics(const struct GUIFont* font, enum GUIIcon icon, unsigned* w, unsigned* h) {
69 UNUSED(font);
70 if (icon >= GUI_ICON_MAX) {
71 if (w) {
72 *w = 0;
73 }
74 if (h) {
75 *h = 0;
76 }
77 } else {
78 if (w) {
79 *w = defaultIconMetrics[icon].width * 2;
80 }
81 if (h) {
82 *h = defaultIconMetrics[icon].height * 2;
83 }
84 }
85}
86
87void GUIFontDrawGlyph(const struct GUIFont* font, int x, int y, uint32_t color, uint32_t glyph) {
88 color = (color >> 24) | (color << 8);
89 GXTexObj tex;
90 // Grumble grumble, libogc is bad about const-correctness
91 struct GUIFont* ncfont = font;
92 TPL_GetTexture(&ncfont->tdf, 0, &tex);
93 GX_LoadTexObj(&tex, GX_TEXMAP0);
94
95 GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
96 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
97 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
98
99 if (glyph > 0x7F) {
100 glyph = '?';
101 }
102 struct GUIFontGlyphMetric metric = defaultFontMetrics[glyph];
103 s16 tx = (glyph & 15) * CELL_WIDTH + metric.padding.left * 2;
104 s16 ty = (glyph >> 4) * CELL_HEIGHT + metric.padding.top * 2;
105 GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
106 GX_Position2s16(x, y - GLYPH_HEIGHT + metric.padding.top * 2);
107 GX_Color1u32(color);
108 GX_TexCoord2f32(tx / 512.f, ty / 256.f);
109
110 GX_Position2s16(x + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2, y - GLYPH_HEIGHT + metric.padding.top * 2);
111 GX_Color1u32(color);
112 GX_TexCoord2f32((tx + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2) / 512.f, ty / 256.f);
113
114 GX_Position2s16(x + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2, y - GLYPH_HEIGHT + CELL_HEIGHT - metric.padding.bottom * 2);
115 GX_Color1u32(color);
116 GX_TexCoord2f32((tx + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2) / 512.f, (ty + CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2) / 256.f);
117
118 GX_Position2s16(x, y - GLYPH_HEIGHT + CELL_HEIGHT - metric.padding.bottom * 2);
119 GX_Color1u32(color);
120 GX_TexCoord2f32(tx / 512.f, (ty + CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2) / 256.f);
121 GX_End();
122}
123
124void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
125 if (icon >= GUI_ICON_MAX) {
126 return;
127 }
128
129 color = (color >> 24) | (color << 8);
130 GXTexObj tex;
131
132 struct GUIFont* ncfont = font;
133 TPL_GetTexture(&ncfont->iconsTdf, 0, &tex);
134 GX_LoadTexObj(&tex, GX_TEXMAP0);
135
136 GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
137 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
138 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
139
140 struct GUIIconMetric metric = defaultIconMetrics[icon];
141 switch (align & GUI_ALIGN_HCENTER) {
142 case GUI_ALIGN_HCENTER:
143 x -= metric.width;
144 break;
145 case GUI_ALIGN_RIGHT:
146 x -= metric.width * 2;
147 break;
148 }
149 switch (align & GUI_ALIGN_VCENTER) {
150 case GUI_ALIGN_VCENTER:
151 y -= metric.height;
152 break;
153 case GUI_ALIGN_BOTTOM:
154 y -= metric.height * 2;
155 break;
156 }
157
158 float u[4];
159 float v[4];
160
161 switch (orient) {
162 case GUI_ORIENT_0:
163 default:
164 // TODO: Rotations
165 u[0] = u[3] = metric.x / 256.f;
166 u[1] = u[2] = (metric.x + metric.width) / 256.f;
167 v[0] = v[1] = (metric.y + metric.height) / 64.f;
168 v[2] = v[3] = metric.y / 64.f;
169 break;
170 case GUI_ORIENT_HMIRROR:
171 u[0] = u[3] = (metric.x + metric.width) / 256.f;
172 u[1] = u[2] = metric.x / 256.f;
173 v[0] = v[1] = (metric.y + metric.height) / 64.f;
174 v[2] = v[3] = metric.y / 64.f;
175 break;
176 case GUI_ORIENT_VMIRROR:
177 u[0] = u[3] = metric.x / 256.f;
178 u[1] = u[2] = (metric.x + metric.width) / 256.f;
179 v[0] = v[1] = metric.y / 64.f;
180 v[2] = v[3] = (metric.y + metric.height) / 64.f;
181 break;
182 }
183
184 GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
185 GX_Position2s16(x, y + metric.height * 2);
186 GX_Color1u32(color);
187 GX_TexCoord2f32(u[0], v[0]);
188
189 GX_Position2s16(x + metric.width * 2, y + metric.height * 2);
190 GX_Color1u32(color);
191 GX_TexCoord2f32(u[1], v[1]);
192
193 GX_Position2s16(x + metric.width * 2, y);
194 GX_Color1u32(color);
195 GX_TexCoord2f32(u[2], v[2]);
196
197 GX_Position2s16(x, y);
198 GX_Color1u32(color);
199 GX_TexCoord2f32(u[3], v[3]);
200 GX_End();
201}
202
203void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) {
204 if (icon >= GUI_ICON_MAX) {
205 return;
206 }
207
208 color = (color >> 24) | (color << 8);
209 GXTexObj tex;
210
211 struct GUIFont* ncfont = font;
212 TPL_GetTexture(&ncfont->iconsTdf, 0, &tex);
213 GX_LoadTexObj(&tex, GX_TEXMAP0);
214
215 GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
216 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
217 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
218
219 struct GUIIconMetric metric = defaultIconMetrics[icon];
220
221 float u[4];
222 float v[4];
223
224 if (!h) {
225 h = metric.height * 2;
226 }
227 if (!w) {
228 w = metric.width * 2;
229 }
230
231 u[0] = u[3] = metric.x / 256.f;
232 u[1] = u[2] = (metric.x + metric.width) / 256.f;
233 v[0] = v[1] = (metric.y + metric.height) / 64.f;
234 v[2] = v[3] = metric.y / 64.f;
235
236 GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
237 GX_Position2s16(x, y + h);
238 GX_Color1u32(color);
239 GX_TexCoord2f32(u[0], v[0]);
240
241 GX_Position2s16(x + w, y + h);
242 GX_Color1u32(color);
243 GX_TexCoord2f32(u[1], v[1]);
244
245 GX_Position2s16(x + w, y);
246 GX_Color1u32(color);
247 GX_TexCoord2f32(u[2], v[2]);
248
249 GX_Position2s16(x, y);
250 GX_Color1u32(color);
251 GX_TexCoord2f32(u[3], v[3]);
252 GX_End();
253}