kick
|
00001 // 00002 // Created by morten on 30/06/14. 00003 // 00004 00005 #include "kick/2d/font.h" 00006 #include "kick/core/project.h" 00007 #include "kick/core/debug.h" 00008 #include <string> 00009 #include <sstream> 00010 #include <iostream> 00011 00012 using namespace std; 00013 00014 namespace kick{ 00015 Font::Font() { 00016 fShader = Project::loadShader("assets/shaders/font.shader"); 00017 } 00018 00019 Font::~Font() { 00020 } 00021 00022 std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) { 00023 elems.clear(); 00024 std::stringstream ss(s); 00025 std::string item; 00026 while (std::getline(ss, item, delim)) { 00027 if (item.length()>0){ 00028 elems.push_back(item); 00029 } 00030 } 00031 return elems; 00032 } 00033 00034 bool Font::loadFntFile(string filename) { 00035 string texturename = filename.substr(0, filename.size()-4) + ".png"; 00036 mFontMap.clear(); 00037 mKerning.clear(); 00038 TextureSampler sampler; 00039 sampler.filterMag = TextureFilter::Linear; 00040 sampler.filterMin = TextureFilter::LinearMipmapLinear; 00041 00042 setTexture(Project::loadTexture2D(texturename, sampler)); 00043 if (!mTexture){ 00044 logWarning(string("Cannot load font texture file ")+texturename); 00045 return false; 00046 } 00047 string fntFile; 00048 if (!Project::loadTextResource(filename,fntFile)){ 00049 logWarning(string("Cannot load font text file ")+filename); 00050 return false; 00051 } 00052 std::istringstream f{fntFile}; 00053 std::string line; 00054 std::vector<string> elems; 00055 std::vector<string> keyval; 00056 while (std::getline(f, line)) { 00057 split(line, ' ', elems); 00058 if (elems.empty()) 00059 continue; 00060 if (elems[0] == "info") { 00061 } else if (elems[0] == "common") { 00062 for (int i=1;i<elems.size();i++) { 00063 split(elems[i], '=', keyval); 00064 if (keyval[0] == "lineHeight"){ 00065 mLineHeight = stoi(keyval[1]); 00066 } else if (keyval[0] == "base"){ 00067 mBase = stoi(keyval[1]); 00068 } else if (keyval[0] == "scaleW"){ 00069 mScaleW = stoi(keyval[1]); 00070 } else if (keyval[0] == "scaleH"){ 00071 mScaleH = stoi(keyval[1]); 00072 } else if (keyval[0] == "pages"){ 00073 mPages = stoi(keyval[1]); 00074 } 00075 } 00076 } else if (elems[0] == "page") { 00077 } else if (elems[0] == "chars") { 00078 } else if (elems[0] == "char") { 00079 FontChar fc{}; 00080 int id = -1; 00081 for (int i=1;i<elems.size();i++){ 00082 split(elems[i], '=', keyval); 00083 if (keyval[0] == "id"){ 00084 id = stoi(keyval[1]); 00085 } else if (keyval[0] == "x"){ 00086 fc.x = stoi(keyval[1]); 00087 } else if (keyval[0] == "y"){ 00088 fc.y = stoi(keyval[1]); 00089 } else if (keyval[0] == "width"){ 00090 fc.width = stoi(keyval[1]); 00091 } else if (keyval[0] == "height"){ 00092 fc.height = stoi(keyval[1]); 00093 } else if (keyval[0] == "xoffset"){ 00094 fc.xoffset = stoi(keyval[1]); 00095 } else if (keyval[0] == "yoffset"){ 00096 fc.yoffset = stoi(keyval[1]); 00097 } else if (keyval[0] == "xadvance"){ 00098 fc.xadvance = stoi(keyval[1]); 00099 } else if (keyval[0] == "page"){ 00100 fc.page = stoi(keyval[1]); 00101 } else if (keyval[0] == "chnl"){ 00102 fc.chnl = stoi(keyval[1]); 00103 } else if (keyval[0] == "letter"){ 00104 // f.letter = keyval[1].substr (1, (unsigned long) (keyval[1].length()-2)); 00105 } 00106 } 00107 mFontMap[id] = fc; 00108 } else if (elems[0] == "kernings") { 00109 00110 } else if (elems[0] == "kerning") { 00111 int first =0; 00112 int second=0; 00113 int amount=0; 00114 for (int i=1;i<elems.size();i++) { 00115 00116 split(elems[i], '=', keyval); 00117 if (keyval[0] == "first"){ 00118 first =stoi(keyval[1]); 00119 } else if (keyval[0] == "second"){ 00120 second =stoi(keyval[1]); 00121 } else if (keyval[0] == "amount"){ 00122 amount =stoi(keyval[1]); 00123 } 00124 } 00125 mKerning[pair<int,int>{first, second}] = amount; 00126 } else { 00127 cout << "Not found type "<<elems[0]<<endl; 00128 } 00129 elems.clear(); 00130 } 00131 return true; 00132 } 00133 00134 int Font::width(std::string text) { 00135 int sum = 0; 00136 int lastChar = -1; 00137 for (int i=0;i<text.length();i++){ 00138 int f = text[i]; 00139 auto foundChar = mFontMap.find(f); 00140 if (foundChar != mFontMap.end()){ 00141 sum += getKerning(lastChar, f); 00142 if (i == text.length()-1){ 00143 sum += foundChar->second.width; 00144 } else { 00145 sum += foundChar->second.xadvance; 00146 } 00147 lastChar = f; 00148 } else { 00149 cout << "Cannot find char "<<f<<endl; 00150 return -1; 00151 } 00152 } 00153 return sum; 00154 } 00155 00156 int Font::getKerning(int t1, int t2){ 00157 auto foundKerning = mKerning.find(pair<int,int>{t1, t2}); 00158 if (foundKerning != mKerning.end()){ 00159 return foundKerning->second; 00160 } 00161 return 0; 00162 } 00163 00164 int Font::height() { 00165 return mLineHeight; 00166 } 00167 00168 shared_ptr<Texture2D> Font::texture() const { 00169 return mTexture; 00170 } 00171 00172 void Font::setTexture(shared_ptr<Texture2D> texture) { 00173 Font::mTexture = texture; 00174 fontListener.notifyListeners(this); 00175 } 00176 00177 const FontChar Font::getChar(char r) { 00178 auto found = mFontMap.find((int)r); 00179 if (found != mFontMap.end()){ 00180 return found->second; 00181 } else { 00182 return kick::FontChar{0,0,0,0}; 00183 } 00184 } 00185 00186 int Font::scaleW() const { 00187 return mScaleW; 00188 } 00189 00190 int Font::scaleH() const { 00191 return mScaleH; 00192 } 00193 00194 int Font::base() const { 00195 return mBase; 00196 } 00197 00198 void Font::setShader(std::shared_ptr<Shader> shader) { 00199 this->fShader = shader; 00200 fontListener.notifyListeners(this); 00201 } 00202 00203 std::shared_ptr<Shader> Font::getShader() { 00204 return fShader; 00205 } 00206 00207 bool Font::initialized() const { 00208 return mTexture != nullptr; 00209 } 00210 }