00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "xrb_sdlpal.hpp"
00012
00013 #if XRB_PLATFORM == XRB_PLATFORM_SDL
00014
00015 #include "png.h"
00016 #include "ft2build.h"
00017 #include FT_FREETYPE_H // otherwise a very strange compile error occurs.
00018 #include "xrb_asciifont.hpp"
00019 #include "xrb_event.hpp"
00020 #include "xrb_gl.hpp"
00021 #include "xrb_input_events.hpp"
00022 #include "xrb_inputstate.hpp"
00023 #include "xrb_key.hpp"
00024 #include "xrb_screen.hpp"
00025 #include "xrb_texture.hpp"
00026
00027 #if defined(WORDS_BIGENDIAN)
00028 #define SDL_RMASK 0xFF000000
00029 #define SDL_GMASK 0x00FF0000
00030 #define SDL_BMASK 0x0000FF00
00031 #define SDL_AMASK 0x000000FF
00032 #else // !defined(WORDS_BIGENDIAN)
00033 #define SDL_RMASK 0x000000FF
00034 #define SDL_GMASK 0x0000FF00
00035 #define SDL_BMASK 0x00FF0000
00036 #define SDL_AMASK 0xFF000000
00037 #endif // !defined(WORDS_BIGENDIAN)
00038
00039 namespace {
00040
00041 Xrb::Key::Code TranslateSDLKey (SDLKey sdl_key)
00042 {
00043 static Xrb::Key::Code s_key_lookup[SDLK_LAST];
00044 static bool s_key_lookup_is_initialized = false;
00045 if (!s_key_lookup_is_initialized)
00046 {
00047 for (Xrb::Sint32 i = 0; i < SDLK_LAST; ++i)
00048 s_key_lookup[i] = Xrb::Key::INVALID;
00049
00050 s_key_lookup[SDLK_UNKNOWN] = Xrb::Key::UNKNOWN;
00051 s_key_lookup[SDL_BUTTON_LEFT] = Xrb::Key::LEFTMOUSE;
00052 s_key_lookup[SDL_BUTTON_MIDDLE] = Xrb::Key::MIDDLEMOUSE;
00053 s_key_lookup[SDL_BUTTON_RIGHT] = Xrb::Key::RIGHTMOUSE;
00054 s_key_lookup[SDL_BUTTON_WHEELUP] = Xrb::Key::MOUSEWHEELUP;
00055 s_key_lookup[SDL_BUTTON_WHEELDOWN] = Xrb::Key::MOUSEWHEELDOWN;
00056 s_key_lookup[SDLK_BACKSPACE] = Xrb::Key::BACKSPACE;
00057 s_key_lookup[SDLK_TAB] = Xrb::Key::TAB;
00058 s_key_lookup[SDLK_CLEAR] = Xrb::Key::CLEAR;
00059 s_key_lookup[SDLK_RETURN] = Xrb::Key::RETURN;
00060 s_key_lookup[SDLK_PAUSE] = Xrb::Key::PAUSE;
00061 s_key_lookup[SDLK_ESCAPE] = Xrb::Key::ESCAPE;
00062 s_key_lookup[SDLK_SPACE] = Xrb::Key::SPACE;
00063 s_key_lookup[SDLK_QUOTE] = Xrb::Key::QUOTE;
00064 s_key_lookup[SDLK_COMMA] = Xrb::Key::COMMA;
00065 s_key_lookup[SDLK_MINUS] = Xrb::Key::MINUS;
00066 s_key_lookup[SDLK_PERIOD] = Xrb::Key::PERIOD;
00067 s_key_lookup[SDLK_SLASH] = Xrb::Key::SLASH;
00068 s_key_lookup[SDLK_0] = Xrb::Key::ZERO;
00069 s_key_lookup[SDLK_1] = Xrb::Key::ONE;
00070 s_key_lookup[SDLK_2] = Xrb::Key::TWO;
00071 s_key_lookup[SDLK_3] = Xrb::Key::THREE;
00072 s_key_lookup[SDLK_4] = Xrb::Key::FOUR;
00073 s_key_lookup[SDLK_5] = Xrb::Key::FIVE;
00074 s_key_lookup[SDLK_6] = Xrb::Key::SIX;
00075 s_key_lookup[SDLK_7] = Xrb::Key::SEVEN;
00076 s_key_lookup[SDLK_8] = Xrb::Key::EIGHT;
00077 s_key_lookup[SDLK_9] = Xrb::Key::NINE;
00078 s_key_lookup[SDLK_SEMICOLON] = Xrb::Key::SEMICOLON;
00079 s_key_lookup[SDLK_EQUALS] = Xrb::Key::EQUALS;
00080 s_key_lookup[SDLK_LEFTBRACKET] = Xrb::Key::LEFTBRACKET;
00081 s_key_lookup[SDLK_BACKSLASH] = Xrb::Key::BACKSLASH;
00082 s_key_lookup[SDLK_RIGHTBRACKET] = Xrb::Key::RIGHTBRACKET;
00083 s_key_lookup[SDLK_BACKQUOTE] = Xrb::Key::BACKQUOTE;
00084 s_key_lookup[SDLK_a] = Xrb::Key::A;
00085 s_key_lookup[SDLK_b] = Xrb::Key::B;
00086 s_key_lookup[SDLK_c] = Xrb::Key::C;
00087 s_key_lookup[SDLK_d] = Xrb::Key::D;
00088 s_key_lookup[SDLK_e] = Xrb::Key::E;
00089 s_key_lookup[SDLK_f] = Xrb::Key::F;
00090 s_key_lookup[SDLK_g] = Xrb::Key::G;
00091 s_key_lookup[SDLK_h] = Xrb::Key::H;
00092 s_key_lookup[SDLK_i] = Xrb::Key::I;
00093 s_key_lookup[SDLK_j] = Xrb::Key::J;
00094 s_key_lookup[SDLK_k] = Xrb::Key::K;
00095 s_key_lookup[SDLK_l] = Xrb::Key::L;
00096 s_key_lookup[SDLK_m] = Xrb::Key::M;
00097 s_key_lookup[SDLK_n] = Xrb::Key::N;
00098 s_key_lookup[SDLK_o] = Xrb::Key::O;
00099 s_key_lookup[SDLK_p] = Xrb::Key::P;
00100 s_key_lookup[SDLK_q] = Xrb::Key::Q;
00101 s_key_lookup[SDLK_r] = Xrb::Key::R;
00102 s_key_lookup[SDLK_s] = Xrb::Key::S;
00103 s_key_lookup[SDLK_t] = Xrb::Key::T;
00104 s_key_lookup[SDLK_u] = Xrb::Key::U;
00105 s_key_lookup[SDLK_v] = Xrb::Key::V;
00106 s_key_lookup[SDLK_w] = Xrb::Key::W;
00107 s_key_lookup[SDLK_x] = Xrb::Key::X;
00108 s_key_lookup[SDLK_y] = Xrb::Key::Y;
00109 s_key_lookup[SDLK_z] = Xrb::Key::Z;
00110 s_key_lookup[SDLK_DELETE] = Xrb::Key::DELETE;
00111 s_key_lookup[SDLK_WORLD_0] = Xrb::Key::WORLD_0;
00112 s_key_lookup[SDLK_WORLD_1] = Xrb::Key::WORLD_1;
00113 s_key_lookup[SDLK_WORLD_2] = Xrb::Key::WORLD_2;
00114 s_key_lookup[SDLK_WORLD_3] = Xrb::Key::WORLD_3;
00115 s_key_lookup[SDLK_WORLD_4] = Xrb::Key::WORLD_4;
00116 s_key_lookup[SDLK_WORLD_5] = Xrb::Key::WORLD_5;
00117 s_key_lookup[SDLK_WORLD_6] = Xrb::Key::WORLD_6;
00118 s_key_lookup[SDLK_WORLD_7] = Xrb::Key::WORLD_7;
00119 s_key_lookup[SDLK_WORLD_8] = Xrb::Key::WORLD_8;
00120 s_key_lookup[SDLK_WORLD_9] = Xrb::Key::WORLD_9;
00121 s_key_lookup[SDLK_WORLD_10] = Xrb::Key::WORLD_10;
00122 s_key_lookup[SDLK_WORLD_11] = Xrb::Key::WORLD_11;
00123 s_key_lookup[SDLK_WORLD_12] = Xrb::Key::WORLD_12;
00124 s_key_lookup[SDLK_WORLD_13] = Xrb::Key::WORLD_13;
00125 s_key_lookup[SDLK_WORLD_14] = Xrb::Key::WORLD_14;
00126 s_key_lookup[SDLK_WORLD_15] = Xrb::Key::WORLD_15;
00127 s_key_lookup[SDLK_WORLD_16] = Xrb::Key::WORLD_16;
00128 s_key_lookup[SDLK_WORLD_17] = Xrb::Key::WORLD_17;
00129 s_key_lookup[SDLK_WORLD_18] = Xrb::Key::WORLD_18;
00130 s_key_lookup[SDLK_WORLD_19] = Xrb::Key::WORLD_19;
00131 s_key_lookup[SDLK_WORLD_20] = Xrb::Key::WORLD_20;
00132 s_key_lookup[SDLK_WORLD_21] = Xrb::Key::WORLD_21;
00133 s_key_lookup[SDLK_WORLD_22] = Xrb::Key::WORLD_22;
00134 s_key_lookup[SDLK_WORLD_23] = Xrb::Key::WORLD_23;
00135 s_key_lookup[SDLK_WORLD_24] = Xrb::Key::WORLD_24;
00136 s_key_lookup[SDLK_WORLD_25] = Xrb::Key::WORLD_25;
00137 s_key_lookup[SDLK_WORLD_26] = Xrb::Key::WORLD_26;
00138 s_key_lookup[SDLK_WORLD_27] = Xrb::Key::WORLD_27;
00139 s_key_lookup[SDLK_WORLD_28] = Xrb::Key::WORLD_28;
00140 s_key_lookup[SDLK_WORLD_29] = Xrb::Key::WORLD_29;
00141 s_key_lookup[SDLK_WORLD_30] = Xrb::Key::WORLD_30;
00142 s_key_lookup[SDLK_WORLD_31] = Xrb::Key::WORLD_31;
00143 s_key_lookup[SDLK_WORLD_32] = Xrb::Key::WORLD_32;
00144 s_key_lookup[SDLK_WORLD_33] = Xrb::Key::WORLD_33;
00145 s_key_lookup[SDLK_WORLD_34] = Xrb::Key::WORLD_34;
00146 s_key_lookup[SDLK_WORLD_35] = Xrb::Key::WORLD_35;
00147 s_key_lookup[SDLK_WORLD_36] = Xrb::Key::WORLD_36;
00148 s_key_lookup[SDLK_WORLD_37] = Xrb::Key::WORLD_37;
00149 s_key_lookup[SDLK_WORLD_38] = Xrb::Key::WORLD_38;
00150 s_key_lookup[SDLK_WORLD_39] = Xrb::Key::WORLD_39;
00151 s_key_lookup[SDLK_WORLD_40] = Xrb::Key::WORLD_40;
00152 s_key_lookup[SDLK_WORLD_41] = Xrb::Key::WORLD_41;
00153 s_key_lookup[SDLK_WORLD_42] = Xrb::Key::WORLD_42;
00154 s_key_lookup[SDLK_WORLD_43] = Xrb::Key::WORLD_43;
00155 s_key_lookup[SDLK_WORLD_44] = Xrb::Key::WORLD_44;
00156 s_key_lookup[SDLK_WORLD_45] = Xrb::Key::WORLD_45;
00157 s_key_lookup[SDLK_WORLD_46] = Xrb::Key::WORLD_46;
00158 s_key_lookup[SDLK_WORLD_47] = Xrb::Key::WORLD_47;
00159 s_key_lookup[SDLK_WORLD_48] = Xrb::Key::WORLD_48;
00160 s_key_lookup[SDLK_WORLD_49] = Xrb::Key::WORLD_49;
00161 s_key_lookup[SDLK_WORLD_50] = Xrb::Key::WORLD_50;
00162 s_key_lookup[SDLK_WORLD_51] = Xrb::Key::WORLD_51;
00163 s_key_lookup[SDLK_WORLD_52] = Xrb::Key::WORLD_52;
00164 s_key_lookup[SDLK_WORLD_53] = Xrb::Key::WORLD_53;
00165 s_key_lookup[SDLK_WORLD_54] = Xrb::Key::WORLD_54;
00166 s_key_lookup[SDLK_WORLD_55] = Xrb::Key::WORLD_55;
00167 s_key_lookup[SDLK_WORLD_56] = Xrb::Key::WORLD_56;
00168 s_key_lookup[SDLK_WORLD_57] = Xrb::Key::WORLD_57;
00169 s_key_lookup[SDLK_WORLD_58] = Xrb::Key::WORLD_58;
00170 s_key_lookup[SDLK_WORLD_59] = Xrb::Key::WORLD_59;
00171 s_key_lookup[SDLK_WORLD_60] = Xrb::Key::WORLD_60;
00172 s_key_lookup[SDLK_WORLD_61] = Xrb::Key::WORLD_61;
00173 s_key_lookup[SDLK_WORLD_62] = Xrb::Key::WORLD_62;
00174 s_key_lookup[SDLK_WORLD_63] = Xrb::Key::WORLD_63;
00175 s_key_lookup[SDLK_WORLD_64] = Xrb::Key::WORLD_64;
00176 s_key_lookup[SDLK_WORLD_65] = Xrb::Key::WORLD_65;
00177 s_key_lookup[SDLK_WORLD_66] = Xrb::Key::WORLD_66;
00178 s_key_lookup[SDLK_WORLD_67] = Xrb::Key::WORLD_67;
00179 s_key_lookup[SDLK_WORLD_68] = Xrb::Key::WORLD_68;
00180 s_key_lookup[SDLK_WORLD_69] = Xrb::Key::WORLD_69;
00181 s_key_lookup[SDLK_WORLD_70] = Xrb::Key::WORLD_70;
00182 s_key_lookup[SDLK_WORLD_71] = Xrb::Key::WORLD_71;
00183 s_key_lookup[SDLK_WORLD_72] = Xrb::Key::WORLD_72;
00184 s_key_lookup[SDLK_WORLD_73] = Xrb::Key::WORLD_73;
00185 s_key_lookup[SDLK_WORLD_74] = Xrb::Key::WORLD_74;
00186 s_key_lookup[SDLK_WORLD_75] = Xrb::Key::WORLD_75;
00187 s_key_lookup[SDLK_WORLD_76] = Xrb::Key::WORLD_76;
00188 s_key_lookup[SDLK_WORLD_77] = Xrb::Key::WORLD_77;
00189 s_key_lookup[SDLK_WORLD_78] = Xrb::Key::WORLD_78;
00190 s_key_lookup[SDLK_WORLD_79] = Xrb::Key::WORLD_79;
00191 s_key_lookup[SDLK_WORLD_80] = Xrb::Key::WORLD_80;
00192 s_key_lookup[SDLK_WORLD_81] = Xrb::Key::WORLD_81;
00193 s_key_lookup[SDLK_WORLD_82] = Xrb::Key::WORLD_82;
00194 s_key_lookup[SDLK_WORLD_83] = Xrb::Key::WORLD_83;
00195 s_key_lookup[SDLK_WORLD_84] = Xrb::Key::WORLD_84;
00196 s_key_lookup[SDLK_WORLD_85] = Xrb::Key::WORLD_85;
00197 s_key_lookup[SDLK_WORLD_86] = Xrb::Key::WORLD_86;
00198 s_key_lookup[SDLK_WORLD_87] = Xrb::Key::WORLD_87;
00199 s_key_lookup[SDLK_WORLD_88] = Xrb::Key::WORLD_88;
00200 s_key_lookup[SDLK_WORLD_89] = Xrb::Key::WORLD_89;
00201 s_key_lookup[SDLK_WORLD_90] = Xrb::Key::WORLD_90;
00202 s_key_lookup[SDLK_WORLD_91] = Xrb::Key::WORLD_91;
00203 s_key_lookup[SDLK_WORLD_92] = Xrb::Key::WORLD_92;
00204 s_key_lookup[SDLK_WORLD_93] = Xrb::Key::WORLD_93;
00205 s_key_lookup[SDLK_WORLD_94] = Xrb::Key::WORLD_94;
00206 s_key_lookup[SDLK_WORLD_95] = Xrb::Key::WORLD_95;
00207 s_key_lookup[SDLK_KP0] = Xrb::Key::KP0;
00208 s_key_lookup[SDLK_KP1] = Xrb::Key::KP1;
00209 s_key_lookup[SDLK_KP2] = Xrb::Key::KP2;
00210 s_key_lookup[SDLK_KP3] = Xrb::Key::KP3;
00211 s_key_lookup[SDLK_KP4] = Xrb::Key::KP4;
00212 s_key_lookup[SDLK_KP5] = Xrb::Key::KP5;
00213 s_key_lookup[SDLK_KP6] = Xrb::Key::KP6;
00214 s_key_lookup[SDLK_KP7] = Xrb::Key::KP7;
00215 s_key_lookup[SDLK_KP8] = Xrb::Key::KP8;
00216 s_key_lookup[SDLK_KP9] = Xrb::Key::KP9;
00217 s_key_lookup[SDLK_KP_PERIOD] = Xrb::Key::KP_PERIOD;
00218 s_key_lookup[SDLK_KP_DIVIDE] = Xrb::Key::KP_DIVIDE;
00219 s_key_lookup[SDLK_KP_MULTIPLY] = Xrb::Key::KP_MULTIPLY;
00220 s_key_lookup[SDLK_KP_MINUS] = Xrb::Key::KP_MINUS;
00221 s_key_lookup[SDLK_KP_PLUS] = Xrb::Key::KP_PLUS;
00222 s_key_lookup[SDLK_KP_ENTER] = Xrb::Key::KP_ENTER;
00223 s_key_lookup[SDLK_KP_EQUALS] = Xrb::Key::KP_EQUALS;
00224 s_key_lookup[SDLK_UP] = Xrb::Key::UP;
00225 s_key_lookup[SDLK_DOWN] = Xrb::Key::DOWN;
00226 s_key_lookup[SDLK_RIGHT] = Xrb::Key::RIGHT;
00227 s_key_lookup[SDLK_LEFT] = Xrb::Key::LEFT;
00228 s_key_lookup[SDLK_INSERT] = Xrb::Key::INSERT;
00229 s_key_lookup[SDLK_HOME] = Xrb::Key::HOME;
00230 s_key_lookup[SDLK_END] = Xrb::Key::END;
00231 s_key_lookup[SDLK_PAGEUP] = Xrb::Key::PAGEUP;
00232 s_key_lookup[SDLK_PAGEDOWN] = Xrb::Key::PAGEDOWN;
00233 s_key_lookup[SDLK_F1] = Xrb::Key::F1;
00234 s_key_lookup[SDLK_F2] = Xrb::Key::F2;
00235 s_key_lookup[SDLK_F3] = Xrb::Key::F3;
00236 s_key_lookup[SDLK_F4] = Xrb::Key::F4;
00237 s_key_lookup[SDLK_F5] = Xrb::Key::F5;
00238 s_key_lookup[SDLK_F6] = Xrb::Key::F6;
00239 s_key_lookup[SDLK_F7] = Xrb::Key::F7;
00240 s_key_lookup[SDLK_F8] = Xrb::Key::F8;
00241 s_key_lookup[SDLK_F9] = Xrb::Key::F9;
00242 s_key_lookup[SDLK_F10] = Xrb::Key::F10;
00243 s_key_lookup[SDLK_F11] = Xrb::Key::F11;
00244 s_key_lookup[SDLK_F12] = Xrb::Key::F12;
00245 s_key_lookup[SDLK_F13] = Xrb::Key::F13;
00246 s_key_lookup[SDLK_F14] = Xrb::Key::F14;
00247 s_key_lookup[SDLK_F15] = Xrb::Key::F15;
00248 s_key_lookup[SDLK_NUMLOCK] = Xrb::Key::NUMLOCK;
00249 s_key_lookup[SDLK_CAPSLOCK] = Xrb::Key::CAPSLOCK;
00250 s_key_lookup[SDLK_SCROLLOCK] = Xrb::Key::SCROLLLOCK;
00251 s_key_lookup[SDLK_RSHIFT] = Xrb::Key::RSHIFT;
00252 s_key_lookup[SDLK_LSHIFT] = Xrb::Key::LSHIFT;
00253 s_key_lookup[SDLK_RCTRL] = Xrb::Key::RCTRL;
00254 s_key_lookup[SDLK_LCTRL] = Xrb::Key::LCTRL;
00255 s_key_lookup[SDLK_RALT] = Xrb::Key::RALT;
00256 s_key_lookup[SDLK_LALT] = Xrb::Key::LALT;
00257 s_key_lookup[SDLK_RMETA] = Xrb::Key::RMETA;
00258 s_key_lookup[SDLK_LMETA] = Xrb::Key::LMETA;
00259 s_key_lookup[SDLK_LSUPER] = Xrb::Key::LWINBLOWS;
00260 s_key_lookup[SDLK_RSUPER] = Xrb::Key::RWINBLOWS;
00261 s_key_lookup[SDLK_MODE] = Xrb::Key::MODE;
00262 s_key_lookup[SDLK_COMPOSE] = Xrb::Key::COMPOSE;
00263 s_key_lookup[SDLK_HELP] = Xrb::Key::HELP;
00264 s_key_lookup[SDLK_PRINT] = Xrb::Key::PRINT;
00265 s_key_lookup[SDLK_SYSREQ] = Xrb::Key::SYSREQ;
00266 s_key_lookup[SDLK_BREAK] = Xrb::Key::BREAK;
00267 s_key_lookup[SDLK_MENU] = Xrb::Key::MENU;
00268 s_key_lookup[SDLK_POWER] = Xrb::Key::POWER;
00269 s_key_lookup[SDLK_EURO] = Xrb::Key::EURO;
00270 s_key_lookup[SDLK_UNDO] = Xrb::Key::UNDO;
00271 }
00272
00273 ASSERT1(sdl_key >= 0 && sdl_key < SDLK_LAST && "SDLKey out of range");
00274 ASSERT1(s_key_lookup[sdl_key] != Xrb::Key::INVALID && "invalid SDLKey");
00275 return s_key_lookup[sdl_key];
00276 }
00277
00278 Xrb::Key::Modifier TranslateSDLMod (SDLMod sdl_mod)
00279 {
00280 DEBUG1_CODE(static SDLMod const s_all = SDLMod(KMOD_LSHIFT|KMOD_RSHIFT|KMOD_LCTRL|KMOD_RCTRL|KMOD_LALT|KMOD_RALT|KMOD_LMETA|KMOD_RMETA|KMOD_NUM|KMOD_CAPS|KMOD_MODE);)
00281 ASSERT1((sdl_mod & ~s_all) == 0 && "invalid SDLMod");
00282
00283 Xrb::Uint32 retval = 0;
00284 if ((sdl_mod & KMOD_LSHIFT) != 0) retval |= Xrb::Key::MOD_LSHIFT;
00285 if ((sdl_mod & KMOD_RSHIFT) != 0) retval |= Xrb::Key::MOD_RSHIFT;
00286 if ((sdl_mod & KMOD_LCTRL) != 0) retval |= Xrb::Key::MOD_LCTRL;
00287 if ((sdl_mod & KMOD_RCTRL) != 0) retval |= Xrb::Key::MOD_RCTRL;
00288 if ((sdl_mod & KMOD_LALT) != 0) retval |= Xrb::Key::MOD_LALT;
00289 if ((sdl_mod & KMOD_RALT) != 0) retval |= Xrb::Key::MOD_RALT;
00290 if ((sdl_mod & KMOD_LMETA) != 0) retval |= Xrb::Key::MOD_LMETA;
00291 if ((sdl_mod & KMOD_RMETA) != 0) retval |= Xrb::Key::MOD_RMETA;
00292 if ((sdl_mod & KMOD_NUM) != 0) retval |= Xrb::Key::MOD_NUM;
00293 if ((sdl_mod & KMOD_CAPS) != 0) retval |= Xrb::Key::MOD_CAPS;
00294 if ((sdl_mod & KMOD_MODE) != 0) retval |= Xrb::Key::MOD_MODE;
00295 return Xrb::Key::Modifier(retval);
00296 }
00297
00298 }
00299
00300 SDLPal::~SDLPal ()
00301 {
00302 if (m_ft_library != NULL)
00303 {
00304 FT_Done_FreeType(m_ft_library);
00305 m_ft_library = NULL;
00306 }
00307 }
00308
00309 Xrb::Pal *SDLPal::Create ()
00310 {
00311 FT_LibraryRec_ *ft_library = NULL;
00312 FT_Error error = FT_Init_FreeType(&ft_library);
00313 if (error != 0)
00314 {
00315 fprintf(stderr, "SDLPal::Create(); the FreeType library failed to initialize\n");
00316 ft_library = NULL;
00317 }
00318 return new SDLPal(ft_library);
00319 }
00320
00321 Xrb::Pal::Status SDLPal::Initialize ()
00322 {
00323 fprintf(stderr, "SDLPal::Initialize();\n");
00324
00325
00326 if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0)
00327 {
00328 fprintf(stderr, "SDLPal::Initialize(); unable to initialize SDL. error: %s\n", SDL_GetError());
00329 return FAILURE;
00330 }
00331
00332 return SUCCESS;
00333 }
00334
00335 void SDLPal::Shutdown ()
00336 {
00337 fprintf(stderr, "SDLPal::Shutdown();\n");
00338
00339
00340 SDL_WM_GrabInput(SDL_GRAB_OFF);
00341
00342 SDL_Quit();
00343 }
00344
00345 Xrb::Pal::Status SDLPal::InitializeVideo (Xrb::Uint16 width, Xrb::Uint16 height, Xrb::Uint8 bit_depth, bool fullscreen)
00346 {
00347 fprintf(stderr, "SDLPal::InitializeVideo();\n");
00348
00349 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
00350 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
00351 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
00352 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
00353 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
00354
00355 Xrb::Uint32 video_mode_flags = SDL_OPENGL;
00356 if (fullscreen)
00357 video_mode_flags |= SDL_FULLSCREEN;
00358
00359 SDL_Surface *surface = SDL_SetVideoMode(width, height, bit_depth, video_mode_flags);
00360 if (surface == NULL)
00361 {
00362 fprintf(stderr, "SDLPal::InitializeVideo(); could not set the requested video mode\n");
00363 return FAILURE;
00364 }
00365
00366 return SUCCESS;
00367 }
00368
00369 void SDLPal::ShutdownVideo ()
00370 {
00371 fprintf(stderr, "SDLPal::ShutdownVideo();\n");
00372
00373
00374
00375
00376
00377
00378 }
00379
00380 void SDLPal::SetWindowCaption (char const *window_caption)
00381 {
00382 fprintf(stderr, "SDLPal::SetWindowCaption(\"%s\");\n", window_caption);
00383
00384 ASSERT1(window_caption != NULL);
00385
00386 SDL_WM_SetCaption(window_caption, "");
00387 }
00388
00389 Xrb::Uint32 SDLPal::CurrentTime ()
00390 {
00391 return SDL_GetTicks();
00392 }
00393
00394 void SDLPal::Sleep (Xrb::Uint32 milliseconds_to_sleep)
00395 {
00396 SDL_Delay(milliseconds_to_sleep);
00397 }
00398
00399 void SDLPal::FinishFrame ()
00400 {
00401 SDL_GL_SwapBuffers();
00402 }
00403
00404 Xrb::Event *SDLPal::PollEvent (Xrb::Screen const *screen, Xrb::Float time)
00405 {
00406 ASSERT1(screen != NULL);
00407 ASSERT1(time >= 0.0);
00408
00409
00410
00411
00412
00413
00414 Xrb::Event *retval = NULL;
00415 SDL_Event e;
00416 while (retval == NULL && SDL_PollEvent(&e) != 0)
00417 {
00418 switch (e.type)
00419 {
00420 case SDL_KEYDOWN:
00421 retval = new Xrb::EventKeyDown(
00422 TranslateSDLKey(e.key.keysym.sym),
00423 TranslateSDLMod(e.key.keysym.mod),
00424 time);
00425 break;
00426
00427 case SDL_KEYUP:
00428 retval = new Xrb::EventKeyUp(
00429 TranslateSDLKey(e.key.keysym.sym),
00430 TranslateSDLMod(e.key.keysym.mod),
00431 time);
00432 break;
00433
00434 case SDL_MOUSEBUTTONDOWN:
00435 {
00436 SDL_MouseButtonEvent const &mouse_button_event = e.button;
00437 Xrb::ScreenCoordVector2 event_position(
00438 static_cast<Xrb::ScreenCoord>(mouse_button_event.x),
00439 screen->ScreenRect().Height() - static_cast<Xrb::ScreenCoord>(mouse_button_event.y));
00440 if (mouse_button_event.button == SDL_BUTTON_WHEELUP ||
00441 mouse_button_event.button == SDL_BUTTON_WHEELDOWN)
00442 {
00443 retval = new Xrb::EventMouseWheel(
00444 TranslateSDLKey(SDLKey(mouse_button_event.button)),
00445 event_position,
00446 Xrb::Singleton::InputState().Modifier(),
00447 time);
00448 }
00449 else
00450 {
00451 retval = new Xrb::EventMouseButtonDown(
00452 TranslateSDLKey(SDLKey(mouse_button_event.button)),
00453 event_position,
00454 Xrb::Singleton::InputState().Modifier(),
00455 time);
00456 }
00457 break;
00458 }
00459
00460 case SDL_MOUSEBUTTONUP:
00461 {
00462 SDL_MouseButtonEvent const &mouse_button_event = e.button;
00463 Xrb::ScreenCoordVector2 event_position(
00464 static_cast<Xrb::ScreenCoord>(mouse_button_event.x),
00465 screen->ScreenRect().Height() - static_cast<Xrb::ScreenCoord>(mouse_button_event.y));
00466 if (mouse_button_event.button == SDL_BUTTON_WHEELUP ||
00467 mouse_button_event.button == SDL_BUTTON_WHEELDOWN)
00468 {
00469
00470 retval = NULL;
00471 }
00472 else
00473 {
00474 retval = new Xrb::EventMouseButtonUp(
00475 TranslateSDLKey(SDLKey(mouse_button_event.button)),
00476 event_position,
00477 Xrb::Singleton::InputState().Modifier(),
00478 time);
00479 }
00480 break;
00481 }
00482
00483 case SDL_MOUSEMOTION:
00484 {
00485 SDL_MouseMotionEvent const &mouse_motion_event = e.motion;
00486 Xrb::ScreenCoordVector2 event_position(
00487 static_cast<Xrb::ScreenCoord>(mouse_motion_event.x),
00488 screen->ScreenRect().Height() - static_cast<Xrb::ScreenCoord>(mouse_motion_event.y));
00489
00490
00491 Xrb::ScreenCoordVector2 event_delta(
00492 mouse_motion_event.xrel,
00493 -mouse_motion_event.yrel);
00494 retval = new Xrb::EventMouseMotion(
00495 Xrb::Singleton::InputState().IsKeyPressed(Xrb::Key::LEFTMOUSE),
00496 Xrb::Singleton::InputState().IsKeyPressed(Xrb::Key::MIDDLEMOUSE),
00497 Xrb::Singleton::InputState().IsKeyPressed(Xrb::Key::RIGHTMOUSE),
00498 event_position,
00499 event_delta,
00500 Xrb::Singleton::InputState().Modifier(),
00501 time);
00502 break;
00503 }
00504
00505 case SDL_JOYAXISMOTION:
00506 case SDL_JOYBALLMOTION:
00507 case SDL_JOYBUTTONDOWN:
00508 case SDL_JOYBUTTONUP:
00509 case SDL_JOYHATMOTION:
00510
00511 break;
00512
00513 case SDL_QUIT:
00514 retval = new Xrb::EventQuit(time);
00515 break;
00516
00517 case SDL_ACTIVEEVENT:
00518 case SDL_SYSWMEVENT:
00519 case SDL_VIDEORESIZE:
00520 case SDL_VIDEOEXPOSE:
00521
00522 break;
00523
00524 case SDL_USEREVENT:
00525 ASSERT1(false &&
00526 "Bad! BAD human! you shouldn't be making "
00527 "SDL_USEREVENTs. Create a subclass "
00528 "of EventCustom instead.");
00529 break;
00530
00531 default:
00532 ASSERT1(false && "Unknown event type");
00533 break;
00534 }
00535 }
00536
00537
00538
00539 return retval;
00540 }
00541
00542 Xrb::Texture *SDLPal::LoadImage (char const *image_path)
00543 {
00544
00545
00546 ASSERT1(image_path != NULL);
00547
00548
00549
00550
00551 png_structp png_ptr;
00552 png_infop info_ptr;
00553 unsigned int sig_read = 0;
00554 FILE *fp;
00555
00556 if ((fp = fopen(image_path, "rb")) == NULL)
00557 {
00558 fprintf(stderr, "SDLPal::LoadImage(\"%s\"); error opening file\n", image_path);
00559 return NULL;
00560 }
00561
00562 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00563 if (png_ptr == NULL)
00564 {
00565 fclose(fp);
00566 fprintf(stderr, "SDLPal::LoadImage(\"%s\"); error reading PNG file\n", image_path);
00567 return NULL;
00568 }
00569
00570 info_ptr = png_create_info_struct(png_ptr);
00571 if (info_ptr == NULL)
00572 {
00573 fclose(fp);
00574 fprintf(stderr, "SDLPal::LoadImage(\"%s\"); error reading PNG file\n", image_path);
00575 return NULL;
00576 }
00577
00578
00579 if (setjmp(png_jmpbuf(png_ptr)))
00580 {
00581 fclose(fp);
00582 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00583 fprintf(stderr, "SDLPal::LoadImage(\"%s\"); error reading PNG file\n", image_path);
00584 return NULL;
00585 }
00586
00587 png_init_io(png_ptr, fp);
00588 png_set_sig_bytes(png_ptr, sig_read);
00589 png_read_info(png_ptr, info_ptr);
00590
00591 png_uint_32 width, height;
00592 int bit_depth, color_type, interlace_type;
00593 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL);
00594
00595
00596 Xrb::Texture *texture = Xrb::Texture::Create(Xrb::ScreenCoordVector2(width, height), false);
00597 ASSERT1(texture != NULL);
00598
00599
00600 if (color_type == PNG_COLOR_TYPE_PALETTE)
00601 png_set_palette_to_rgb(png_ptr);
00602
00603
00604 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
00605 png_set_gray_1_2_4_to_8(png_ptr);
00606
00607
00608
00609 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00610 png_set_tRNS_to_alpha(png_ptr);
00611
00612
00613
00614 png_read_update_info(png_ptr, info_ptr);
00615 png_bytep *row_pointers = (png_bytepp)png_malloc(png_ptr, height*sizeof(png_bytep));
00616 for (png_uint_32 row = 0; row < height; row++)
00617 row_pointers[row] = png_bytep(texture->Data()) + row*texture->Width()*4;
00618
00619 png_read_image(png_ptr, row_pointers);
00620 png_read_end(png_ptr, info_ptr);
00621
00622
00623
00624
00625 fclose(fp);
00626
00627 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00628
00629 return texture;
00630 }
00631
00632 Xrb::Pal::Status SDLPal::SaveImage (char const *image_path, Xrb::Texture const &texture)
00633 {
00634
00635
00636 ASSERT1(image_path != NULL);
00637
00638
00639
00640
00641 FILE *fp;
00642 png_structp png_ptr;
00643 png_infop info_ptr;
00644
00645 fp = fopen(image_path, "wb");
00646 if (fp == NULL)
00647 {
00648 fprintf(stderr, "SDLPal::SaveImage(\"%s\"); error opening file\n", image_path);
00649 return FAILURE;
00650 }
00651
00652 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00653 if (png_ptr == NULL)
00654 {
00655 fprintf(stderr, "SDLPal::SaveImage(\"%s\"); error in PNG creation\n", image_path);
00656 fclose(fp);
00657 return FAILURE;
00658 }
00659
00660 info_ptr = png_create_info_struct(png_ptr);
00661 if (info_ptr == NULL)
00662 {
00663 fprintf(stderr, "SDLPal::SaveImage(\"%s\"); error in PNG creation\n", image_path);
00664 fclose(fp);
00665 png_destroy_write_struct(&png_ptr, png_infopp_NULL);
00666 return FAILURE;
00667 }
00668
00669 if (setjmp(png_jmpbuf(png_ptr)))
00670 {
00671 fprintf(stderr, "SDLPal::SaveImage(\"%s\"); error in PNG creation\n", image_path);
00672 fclose(fp);
00673 png_destroy_write_struct(&png_ptr, &info_ptr);
00674 return FAILURE;
00675 }
00676
00677 png_init_io(png_ptr, fp);
00678
00679 png_bytep *row_pointers = (png_bytepp)png_malloc(png_ptr, texture.Height()*sizeof(png_bytep));
00680 for (Xrb::ScreenCoord row = 0; row < texture.Height(); ++row)
00681 row_pointers[row] = png_bytep(texture.Data()) + row*texture.Width()*4;
00682
00683
00684 png_set_IHDR(png_ptr, info_ptr, texture.Width(), texture.Height(), 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 png_write_info(png_ptr, info_ptr);
00699 png_write_image(png_ptr, row_pointers);
00700 png_write_end(png_ptr, info_ptr);
00701 png_destroy_write_struct(&png_ptr, &info_ptr);
00702 fclose(fp);
00703 return SUCCESS;
00704 }
00705
00706
00707 namespace {
00708
00709
00710 class FontFace
00711 {
00712 public:
00713
00714 FontFace (std::string const &path, FT_FaceRec_ *face)
00715 :
00716 m_path(path),
00717 m_face(face)
00718 {
00719 ASSERT1(m_face != NULL);
00720 }
00721 ~FontFace ()
00722 {
00723 FT_Done_Face(m_face);
00724 }
00725
00726 static FontFace *Create (std::string const &path, FT_LibraryRec_ *ft_library)
00727 {
00728 ASSERT1(ft_library != NULL);
00729
00730 FontFace *retval = NULL;
00731
00732 FT_Error error;
00733 FT_FaceRec_ *face;
00734
00735 error = FT_New_Face(ft_library, path.c_str(), 0, &face);
00736 if (error != 0)
00737 return retval;
00738
00739 ASSERT1(face != NULL);
00740
00741
00742
00743
00744 if (path.find_last_of(".pfa") < path.length() ||
00745 path.find_last_of(".pfb") < path.length())
00746 {
00747 std::string metrics_path(path.substr(0, path.length()-4));
00748 metrics_path += ".afm";
00749
00750
00751 FT_Attach_File(face, metrics_path.c_str());
00752
00753 metrics_path = path.substr(0, path.length()-4);
00754 metrics_path += ".pfm";
00755
00756
00757 FT_Attach_File(face, metrics_path.c_str());
00758 }
00759
00760 if (FT_HAS_KERNING(face))
00761 fprintf(stderr, "FontFace::Create(\"%s\"); loaded font with kerning\n", path.c_str());
00762 else
00763 fprintf(stderr, "FontFace::Create(\"%s\"); loaded font without kerning\n", path.c_str());
00764
00765 return new FontFace(path, face);
00766 }
00767
00768 std::string const &Path () const { return m_path; }
00769 FT_FaceRec_ *FTFace () const { return m_face; }
00770
00771 private:
00772
00773 std::string const m_path;
00774 FT_FaceRec_ *const m_face;
00775 };
00776
00777 Xrb::Uint32 UsedTextureArea (
00778 Xrb::ScreenCoordVector2 const &texture_size,
00779 Xrb::AsciiFont::GlyphSpecification *const *const sorted_glyph_specification)
00780 {
00781 ASSERT1(texture_size[Xrb::Dim::X] > 0);
00782 ASSERT1(texture_size[Xrb::Dim::Y] > 0);
00783
00784
00785
00786 ASSERT1((texture_size[Xrb::Dim::X] & (texture_size[Xrb::Dim::X] - 1)) == 0);
00787 ASSERT1((texture_size[Xrb::Dim::Y] & (texture_size[Xrb::Dim::Y] - 1)) == 0);
00788 ASSERT1(sorted_glyph_specification != NULL);
00789
00790 Xrb::ScreenCoord packed_width = 0;
00791 Xrb::ScreenCoordVector2 current_packing_area = Xrb::ScreenCoordVector2::ms_zero;
00792 Xrb::Uint32 index = 0;
00793 Xrb::Uint32 total_area = 0;
00794
00795 while (packed_width + current_packing_area[Xrb::Dim::X] <= texture_size[Xrb::Dim::X] &&
00796 index < Xrb::AsciiFont::RENDERED_GLYPH_COUNT)
00797 {
00798 Xrb::AsciiFont::GlyphSpecification *glyph = sorted_glyph_specification[index];
00799 ASSERT1(glyph != NULL);
00800
00801
00802
00803 if (glyph->m_size[Xrb::Dim::X] > texture_size[Xrb::Dim::X] ||
00804 glyph->m_size[Xrb::Dim::Y] > texture_size[Xrb::Dim::Y])
00805 return 0;
00806
00807
00808
00809 if (current_packing_area[Xrb::Dim::Y] + glyph->m_size[Xrb::Dim::Y] > texture_size[Xrb::Dim::Y])
00810 {
00811 packed_width += current_packing_area[Xrb::Dim::X];
00812 current_packing_area[Xrb::Dim::Y] = 0;
00813 }
00814
00815 else
00816 {
00817 total_area += glyph->m_size[Xrb::Dim::X] * glyph->m_size[Xrb::Dim::Y];
00818 glyph->m_texture_coordinates.SetComponents(
00819 packed_width,
00820 current_packing_area[Xrb::Dim::Y]);
00821 if (current_packing_area[Xrb::Dim::X] < glyph->m_size[Xrb::Dim::X])
00822 current_packing_area[Xrb::Dim::X] = glyph->m_size[Xrb::Dim::X];
00823 current_packing_area[Xrb::Dim::Y] += glyph->m_size[Xrb::Dim::Y];
00824 ++index;
00825 }
00826 ASSERT1(current_packing_area[Xrb::Dim::Y] <= texture_size[Xrb::Dim::Y]);
00827 }
00828
00829
00830
00831 if (packed_width <= texture_size[Xrb::Dim::X] && index == Xrb::AsciiFont::RENDERED_GLYPH_COUNT)
00832 {
00833 ASSERT1(total_area > 0);
00834 return total_area;
00835 }
00836 else
00837 return 0;
00838 }
00839
00840 Xrb::ScreenCoordVector2 FindSmallestFittingTextureSize (
00841 Xrb::AsciiFont::GlyphSpecification *const *const sorted_glyph_specification)
00842 {
00843 GLint max_texture_size;
00844
00845 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
00846
00847 Xrb::Dim::Component increase = Xrb::Dim::Y;
00848 Xrb::ScreenCoordVector2 texture_size(32, 32);
00849 while(texture_size[Xrb::Dim::X] <= static_cast<Xrb::ScreenCoord>(max_texture_size) &&
00850 texture_size[Xrb::Dim::Y] <= static_cast<Xrb::ScreenCoord>(max_texture_size))
00851 {
00852 Xrb::Uint32 used_area = UsedTextureArea(texture_size, sorted_glyph_specification);
00853 DEBUG1_CODE(Xrb::Uint32 total_area = texture_size[Xrb::Dim::X] * texture_size[Xrb::Dim::Y]);
00854 ASSERT1(used_area <= total_area);
00855 if (used_area > 0)
00856 return texture_size;
00857
00858 texture_size[increase] <<= 1;
00859 increase = (increase == Xrb::Dim::X) ? Xrb::Dim::Y : Xrb::Dim::X;
00860 }
00861
00862 ASSERT0(false && "No texture big enough to hold all glyphs");
00863 return Xrb::ScreenCoordVector2::ms_zero;
00864 }
00865
00866 Xrb::Texture *GenerateTexture (
00867 FontFace const &font_face,
00868 Xrb::ScreenCoordVector2 const &texture_size,
00869 Xrb::AsciiFont::GlyphSpecification glyph_specification[Xrb::AsciiFont::RENDERED_GLYPH_COUNT])
00870 {
00871 Xrb::Texture *texture = Xrb::Texture::Create(texture_size, true);
00872
00873 FT_Error error;
00874 FT_FaceRec_ *ft_face = font_face.FTFace();
00875 for (Xrb::Uint32 i = 0; i < Xrb::AsciiFont::RENDERED_GLYPH_COUNT; ++i)
00876 {
00877 Xrb::AsciiFont::GlyphSpecification &glyph = glyph_specification[i];
00878
00879 error = FT_Load_Glyph(ft_face, FT_Get_Char_Index(ft_face, glyph.m_ascii), FT_LOAD_RENDER);
00880 ASSERT1(error == 0);
00881 ASSERT1(ft_face->glyph->format == FT_GLYPH_FORMAT_BITMAP);
00882
00883
00884
00885 ASSERT1(ft_face->glyph->bitmap.pitch == glyph.m_size[Xrb::Dim::X]);
00886 Xrb::Uint8 const *source_pixel_data = ft_face->glyph->bitmap.buffer;
00887 for (Xrb::Sint32 y = 0; y < glyph.m_size[Xrb::Dim::Y]; ++y)
00888 {
00889 Xrb::Uint8 *dest_pixel_data =
00890 texture->Data() +
00891 (glyph.m_texture_coordinates[Xrb::Dim::Y] + y) * texture_size[Xrb::Dim::X] * 4 +
00892 glyph.m_texture_coordinates[Xrb::Dim::X] * 4;
00893
00894 for (Xrb::Sint32 x = 0; x < glyph.m_size[Xrb::Dim::X]; ++x)
00895 {
00896
00897 *(dest_pixel_data++) = 0xFF;
00898 *(dest_pixel_data++) = 0xFF;
00899 *(dest_pixel_data++) = 0xFF;
00900 *(dest_pixel_data++) = *(source_pixel_data++);
00901 }
00902 }
00903 }
00904
00905 return texture;
00906 }
00907
00908 }
00909
00910 Xrb::Font *SDLPal::LoadFont (char const *font_path, Xrb::ScreenCoord pixel_height)
00911 {
00912 Xrb::AsciiFont *retval = NULL;
00913
00914
00915 retval = Xrb::AsciiFont::CreateFromCache(font_path, pixel_height);
00916 if (retval != NULL)
00917 return retval;
00918
00919
00920
00921 FontFace *font_face = FontFace::Create(font_path, m_ft_library);
00922 if (font_face == NULL)
00923 return retval;
00924
00925 FT_FaceRec_ *ft_face = font_face->FTFace();
00926 ASSERT1(ft_face != NULL);
00927 {
00928 FT_Error error = FT_Set_Pixel_Sizes(ft_face, 0, pixel_height);
00929 if (error != 0)
00930 {
00931 Xrb::Delete(font_face);
00932 return retval;
00933 }
00934 }
00935
00936 bool has_kerning;
00937 Xrb::ScreenCoord baseline_height;
00938 Xrb::AsciiFont::GlyphSpecification glyph_specification[Xrb::AsciiFont::RENDERED_GLYPH_COUNT];
00939 Xrb::FontCoord kern_pair_26_6[Xrb::AsciiFont::RENDERED_GLYPH_COUNT*Xrb::AsciiFont::RENDERED_GLYPH_COUNT];
00940
00941 has_kerning = FT_HAS_KERNING(ft_face) != 0;
00942
00943
00944 {
00945 FT_Error error;
00946 FT_FaceRec_ *ft_face = font_face->FTFace();
00947 Xrb::ScreenCoord tallest_glyph_height = -1;
00948 Xrb::ScreenCoord tallest_glyph_bearing_y = -1;
00949
00950 for (char ascii = Xrb::AsciiFont::RENDERED_GLYPH_LOWEST;
00951 ascii != Xrb::AsciiFont::RENDERED_GLYPH_HIGHEST+1;
00952 ++ascii)
00953 {
00954 error = FT_Load_Glyph(ft_face, FT_Get_Char_Index(ft_face, ascii), FT_LOAD_DEFAULT);
00955 ASSERT1(error == 0);
00956
00957 Xrb::AsciiFont::GlyphSpecification &glyph = glyph_specification[Xrb::AsciiFont::GlyphIndex(ascii)];
00958
00959 glyph.m_ascii = ascii;
00960 glyph.m_size.SetComponents(
00961 ft_face->glyph->metrics.width >> 6,
00962 ft_face->glyph->metrics.height >> 6);
00963 glyph.m_bearing_26_6.SetComponents(
00964 ft_face->glyph->metrics.horiBearingX,
00965 ft_face->glyph->metrics.horiBearingY);
00966 glyph.m_advance_26_6 = ft_face->glyph->metrics.horiAdvance;
00967
00968 if (tallest_glyph_height < glyph.m_size[Xrb::Dim::Y])
00969 {
00970 tallest_glyph_height = glyph.m_size[Xrb::Dim::Y];
00971 tallest_glyph_bearing_y = Xrb::FontToScreenCoord(glyph.m_bearing_26_6[Xrb::Dim::Y]);
00972 }
00973 }
00974
00975 baseline_height =
00976 (pixel_height - tallest_glyph_height) / 2 +
00977 (tallest_glyph_height - tallest_glyph_bearing_y);
00978 }
00979
00980
00981 {
00982 FT_Error error;
00983
00984
00985 if (!has_kerning || (error = FT_Set_Pixel_Sizes(font_face->FTFace(), 0, pixel_height)) != 0)
00986 {
00987 memset(kern_pair_26_6, 0, sizeof(kern_pair_26_6));
00988 }
00989 else
00990 {
00991 FT_Vector delta;
00992 for (Xrb::Uint32 left = 0; left < Xrb::AsciiFont::RENDERED_GLYPH_COUNT; ++left)
00993 {
00994 for (Xrb::Uint32 right = 0; right < Xrb::AsciiFont::RENDERED_GLYPH_COUNT; ++right)
00995 {
00996 FT_Get_Kerning(
00997 font_face->FTFace(),
00998 FT_Get_Char_Index(font_face->FTFace(), Xrb::AsciiFont::AsciiValue(left)),
00999 FT_Get_Char_Index(font_face->FTFace(), Xrb::AsciiFont::AsciiValue(right)),
01000 FT_KERNING_UNFITTED,
01001 &delta);
01002 kern_pair_26_6[left*Xrb::AsciiFont::RENDERED_GLYPH_COUNT + right] = delta.x;
01003 }
01004 }
01005 }
01006 }
01007
01008
01009 Xrb::AsciiFont::GlyphSpecification *sorted_glyph_specification[Xrb::AsciiFont::RENDERED_GLYPH_COUNT];
01010 for (Xrb::Uint32 i = 0; i < Xrb::AsciiFont::RENDERED_GLYPH_COUNT; ++i)
01011 sorted_glyph_specification[i] = &glyph_specification[i];
01012
01013
01014 qsort(
01015 sorted_glyph_specification,
01016 Xrb::AsciiFont::RENDERED_GLYPH_COUNT,
01017 sizeof(Xrb::AsciiFont::GlyphSpecification const *),
01018 Xrb::AsciiFont::GlyphSpecification::SortByWidthFirst);
01019
01020
01021 Xrb::ScreenCoordVector2 smallest_fitting_texture_size =
01022 FindSmallestFittingTextureSize(sorted_glyph_specification);
01023 ASSERT1(smallest_fitting_texture_size != Xrb::ScreenCoordVector2::ms_zero);
01024
01025
01026 Xrb::Texture *font_texture = GenerateTexture(*font_face, smallest_fitting_texture_size, glyph_specification);
01027
01028 Xrb::Delete(font_face);
01029
01030
01031 retval = Xrb::AsciiFont::Create(
01032 font_path,
01033 pixel_height,
01034 has_kerning,
01035 baseline_height,
01036 glyph_specification,
01037 kern_pair_26_6,
01038 font_texture);
01039
01040
01041 retval->CacheToDisk(font_texture);
01042 Xrb::Delete(font_texture);
01043
01044
01045 return retval;
01046 }
01047
01048 #endif // XRB_PLATFORM == XRB_PLATFORM_SDL