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
98 if (glyph > 0x7F) {
99 glyph = '?';
100 }
101 struct GUIFontGlyphMetric metric = defaultFontMetrics[glyph];
102 s16 tx = (glyph & 15) * CELL_WIDTH + metric.padding.left * 2;
103 s16 ty = (glyph >> 4) * CELL_HEIGHT + metric.padding.top * 2;
104 GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
105 GX_Position2s16(x, y - GLYPH_HEIGHT + metric.padding.top * 2);
106 GX_Color1u32(color);
107 GX_TexCoord2f32(tx / 512.f, ty / 256.f);
108
109 GX_Position2s16(x + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2, y - GLYPH_HEIGHT + metric.padding.top * 2);
110 GX_Color1u32(color);
111 GX_TexCoord2f32((tx + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2) / 512.f, ty / 256.f);
112
113 GX_Position2s16(x + CELL_WIDTH - (metric.padding.left + metric.padding.right) * 2, y - GLYPH_HEIGHT + CELL_HEIGHT - metric.padding.bottom * 2);
114 GX_Color1u32(color);
115 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);
116
117 GX_Position2s16(x, y - GLYPH_HEIGHT + CELL_HEIGHT - metric.padding.bottom * 2);
118 GX_Color1u32(color);
119 GX_TexCoord2f32(tx / 512.f, (ty + CELL_HEIGHT - (metric.padding.top + metric.padding.bottom) * 2) / 256.f);
120 GX_End();
121}
122
123void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) {
124 if (icon >= GUI_ICON_MAX) {
125 return;
126 }
127
128 color = (color >> 24) | (color << 8);
129 GXTexObj tex;
130
131 struct GUIFont* ncfont = font;
132 TPL_GetTexture(&ncfont->iconsTdf, 0, &tex);
133 GX_LoadTexObj(&tex, GX_TEXMAP0);
134
135 GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
136 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
137
138 struct GUIIconMetric metric = defaultIconMetrics[icon];
139 switch (align & GUI_ALIGN_HCENTER) {
140 case GUI_ALIGN_HCENTER:
141 x -= metric.width;
142 break;
143 case GUI_ALIGN_RIGHT:
144 x -= metric.width * 2;
145 break;
146 }
147 switch (align & GUI_ALIGN_VCENTER) {
148 case GUI_ALIGN_VCENTER:
149 y -= metric.height;
150 break;
151 case GUI_ALIGN_BOTTOM:
152 y -= metric.height * 2;
153 break;
154 }
155
156 float u[4];
157 float v[4];
158
159 switch (orient) {
160 case GUI_ORIENT_0:
161 default:
162 // TODO: Rotations
163 u[0] = u[3] = metric.x / 256.f;
164 u[1] = u[2] = (metric.x + metric.width) / 256.f;
165 v[0] = v[1] = (metric.y + metric.height) / 64.f;
166 v[2] = v[3] = metric.y / 64.f;
167 break;
168 case GUI_ORIENT_HMIRROR:
169 u[0] = u[3] = (metric.x + metric.width) / 256.f;
170 u[1] = u[2] = metric.x / 256.f;
171 v[0] = v[1] = (metric.y + metric.height) / 64.f;
172 v[2] = v[3] = metric.y / 64.f;
173 break;
174 case GUI_ORIENT_VMIRROR:
175 u[0] = u[3] = metric.x / 256.f;
176 u[1] = u[2] = (metric.x + metric.width) / 256.f;
177 v[0] = v[1] = metric.y / 64.f;
178 v[2] = v[3] = (metric.y + metric.height) / 64.f;
179 break;
180 }
181
182 GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
183 GX_Position2s16(x, y + metric.height * 2);
184 GX_Color1u32(color);
185 GX_TexCoord2f32(u[0], v[0]);
186
187 GX_Position2s16(x + metric.width * 2, y + metric.height * 2);
188 GX_Color1u32(color);
189 GX_TexCoord2f32(u[1], v[1]);
190
191 GX_Position2s16(x + metric.width * 2, y);
192 GX_Color1u32(color);
193 GX_TexCoord2f32(u[2], v[2]);
194
195 GX_Position2s16(x, y);
196 GX_Color1u32(color);
197 GX_TexCoord2f32(u[3], v[3]);
198 GX_End();
199}
200
201void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, uint32_t color, enum GUIIcon icon) {
202 if (icon >= GUI_ICON_MAX) {
203 return;
204 }
205
206 color = (color >> 24) | (color << 8);
207 GXTexObj tex;
208
209 struct GUIFont* ncfont = font;
210 TPL_GetTexture(&ncfont->iconsTdf, 0, &tex);
211 GX_LoadTexObj(&tex, GX_TEXMAP0);
212
213 GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
214 GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
215
216 struct GUIIconMetric metric = defaultIconMetrics[icon];
217
218 float u[4];
219 float v[4];
220
221 if (!h) {
222 h = metric.height * 2;
223 }
224 if (!w) {
225 w = metric.width * 2;
226 }
227
228 u[0] = u[3] = metric.x / 256.f;
229 u[1] = u[2] = (metric.x + metric.width) / 256.f;
230 v[0] = v[1] = (metric.y + metric.height) / 64.f;
231 v[2] = v[3] = metric.y / 64.f;
232
233 GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
234 GX_Position2s16(x, y + h);
235 GX_Color1u32(color);
236 GX_TexCoord2f32(u[0], v[0]);
237
238 GX_Position2s16(x + w, y + h);
239 GX_Color1u32(color);
240 GX_TexCoord2f32(u[1], v[1]);
241
242 GX_Position2s16(x + w, y);
243 GX_Color1u32(color);
244 GX_TexCoord2f32(u[2], v[2]);
245
246 GX_Position2s16(x, y);
247 GX_Color1u32(color);
248 GX_TexCoord2f32(u[3], v[3]);
249 GX_End();
250}