00001 #include "font.h"
00002 #include "application.h"
00003 #include <gctypes.h>
00004 #include <ogc/gx_struct.h>
00005 #include <ogc/cache.h>
00006 #include <vector>
00007 #include <map>
00008 #include <string.h>
00009 #include <malloc.h>
00010
00011 namespace wit {
00012
00072 FontSymbol::FontSymbol() : data(0), texWidth(0), texHeight(0), leftBearing(0), charWidth(0)
00073 {
00074
00075 }
00076
00077 struct FontPrivate {
00078 bool registered;
00079 std::vector<FontSymbol> symbols;
00080 unsigned char wordSpacing;
00081 };
00082
00083 struct FontRegistry {
00084 FontRegistry(const std::string& name) : name(name), next(0) {}
00085 std::string name;
00086 FontPrivate* normal;
00087 FontPrivate* bold;
00088 FontPrivate* italic;
00089 FontPrivate* boldItalic;
00090 FontRegistry* next;
00091 };
00092
00093 static FontRegistry* wit_font_registry = 0;
00094
00095 static FontRegistry* wit_find_font(const std::string& name)
00096 {
00097 FontRegistry* r = wit_font_registry;
00098 while(r) {
00099 if(r->name == name) return r;
00100 r = r->next;
00101 }
00102 return 0;
00103 }
00104
00129 Font::Font() : d(new FontPrivate)
00130 {
00131 d->registered = false;
00132 d->symbols.resize(94);
00133 }
00134
00142 Font::Font(const std::string& fontName, bool bold, bool italic) : d(0)
00143 {
00144 FontRegistry* r = wit_find_font(fontName);
00145 if(r) {
00146 if(!bold && !italic)
00147 d = r->normal;
00148 else if(bold && !italic)
00149 d = r->bold;
00150 else if(!bold && italic)
00151 d = r->italic;
00152 else
00153 d = r->boldItalic;
00154 }
00155 }
00156
00160 Font::~Font()
00161 {
00162 if(d && !d->registered)
00163 delete d;
00164 }
00165
00171 bool Font::isValid() const
00172 {
00173 return d;
00174 }
00175
00183 void Font::setChar(unsigned char symbol, int texWidth, int texHeight, char* data, int leftBearing, int width)
00184 {
00185 if(!d || symbol < 33 || symbol > 126) return;
00186 int length = texWidth * texHeight;
00187 symbol -= 33;
00188 FontSymbol s;
00189 s.texWidth = texWidth;
00190 s.texHeight = texHeight;
00191 s.data = (char*)memalign(32, length);
00192 memcpy(s.data, data, length);
00193 s.leftBearing = leftBearing;
00194 s.charWidth = width;
00195 d->symbols[symbol] = s;
00196 DCFlushRange(s.data, length);
00197 }
00198
00203 FontSymbol Font::charData(unsigned char symbol) const
00204 {
00205 if(!d || symbol < 33 || ((unsigned int)symbol - 33) >= d->symbols.size()) return FontSymbol();
00206 return d->symbols[symbol - 33];
00207 }
00208
00213 void Font::registerFont(const std::string& fontName, bool bold, bool italic, int wordSpacing)
00214 {
00215 if(!d || d->registered) return;
00216
00217 d->registered = true;
00218
00219 FontRegistry* r = wit_find_font(fontName);
00220 if(!r) {
00221 r = new FontRegistry(fontName);
00222 r->normal = 0;
00223 r->bold = 0;
00224 r->italic = 0;
00225 r->boldItalic = 0;
00226 r->next = wit_font_registry;
00227 wit_font_registry = r;
00228 }
00229
00230 d->wordSpacing = wordSpacing;
00231
00232 if(!bold && !italic)
00233 r->normal = d;
00234 else if(bold && !italic)
00235 r->bold = d;
00236 else if(!bold && italic)
00237 r->italic = d;
00238 else
00239 r->boldItalic = d;
00240 }
00241
00245 float Font::draw(float x, float y, const std::string& text, const GXColor& color)
00246 {
00247 if(!d || !d->registered) return x;
00248
00249
00250
00251 Mtx44 perspective;
00252 guOrtho(perspective, 0, wit::Application::instance()->screenHeight(), 0, wit::Application::instance()->screenWidth(), 0, 300);
00253 GX_LoadProjectionMtx(perspective, GX_ORTHOGRAPHIC);
00254
00255 GX_SetNumChans(1);
00256 GX_SetNumTexGens(1);
00257 GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
00258 GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
00259 GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
00260
00261 GX_ClearVtxDesc();
00262 GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
00263 GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
00264 GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
00265
00266 int ct = text.size();
00267 GXTexObj texObj;
00268 for(int i = 0; i < ct; i++) {
00269 if(text[i] < 33) {
00270 x += d->wordSpacing;
00271 continue;
00272 }
00273 FontSymbol s = charData(text[i]);
00274 if(!s.data) continue;
00275 x += int(s.leftBearing);
00276
00277 GX_InitTexObj(&texObj, s.data, s.texWidth, s.texHeight, GX_TF_IA4, GX_CLAMP, GX_CLAMP, GX_FALSE);
00278 GX_LoadTexObj(&texObj, GX_TEXMAP0);
00279 GX_InvalidateTexAll();
00280
00281 GX_Begin(GX_QUADS, GX_VTXFMT7, 4);
00282 GX_Position2f32(x, y);
00283 GX_Color4u8(color.r, color.g, color.b, color.a);
00284 GX_TexCoord2f32(0, 0);
00285 GX_Position2f32(x + s.texWidth, y);
00286 GX_Color4u8(color.r, color.g, color.b, color.a);
00287 GX_TexCoord2f32(1, 0);
00288 GX_Position2f32(x + s.texWidth, y + s.texHeight);
00289 GX_Color4u8(color.r, color.g, color.b, color.a);
00290 GX_TexCoord2f32(1, 1);
00291 GX_Position2f32(x, y + s.texHeight);
00292 GX_Color4u8(color.r, color.g, color.b, color.a);
00293 GX_TexCoord2f32(0, 1);
00294 GX_End();
00295 x += int(s.charWidth) - int(s.leftBearing);
00296 }
00297
00298 return x;
00299 }
00300
00301 }