1 /* 2 Copyright (c) 2013 yvt 3 4 This file is part of OpenSpades. 5 6 OpenSpades is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 OpenSpades is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with OpenSpades. If not, see <http://www.gnu.org/licenses/>. 18 19 */ 20 21 #include "Quake3Font.h" 22 23 #include "IRenderer.h" 24 #include <Core/Debug.h> 25 26 namespace spades { 27 namespace client { Quake3Font(IRenderer * r,IImage * tex,const int * mp,int gh,float sw,bool extended)28 Quake3Font::Quake3Font(IRenderer *r, IImage *tex, const int *mp, int gh, float sw, 29 bool extended) 30 : IFont(r), renderer(r), tex(tex), glyphHeight(gh), spaceWidth(sw) { 31 SPADES_MARK_FUNCTION(); 32 33 tex->AddRef(); 34 for (int i = 0; i < (extended ? 256 : 128); i++) { 35 int x = *(mp++); 36 int y = *(mp++); 37 int w = *(mp++); 38 int adv; 39 if (extended) { 40 adv = *(mp++); 41 } else { 42 adv = w; 43 } 44 45 GlyphInfo info; 46 if (w == -1) { 47 info.type = Invalid; 48 glyphs.push_back(info); 49 continue; 50 } 51 if (adv == PROP_SPACE_WIDTH) { 52 info.type = Space; 53 glyphs.push_back(info); 54 continue; 55 } 56 57 info.type = Image; 58 info.imageRect = AABB2(x, y, w, gh); 59 info.advance = adv; 60 61 glyphs.push_back(info); 62 } 63 64 yMin = 0.f; 65 yMax = (float)gh; 66 } 67 ~Quake3Font()68 Quake3Font::~Quake3Font() { 69 SPADES_MARK_FUNCTION(); 70 tex->Release(); 71 } 72 SetGlyphYRange(float yMin,float yMax)73 void Quake3Font::SetGlyphYRange(float yMin, float yMax) { 74 this->yMin = yMin; 75 this->yMax = yMax; 76 } 77 Measure(const std::string & txt)78 Vector2 Quake3Font::Measure(const std::string &txt) { 79 SPADES_MARK_FUNCTION(); 80 81 float x = 0.f, w = 0.f, h = (float)glyphHeight; 82 for (size_t i = 0; i < txt.size();) { 83 size_t chrLen = 0; 84 uint32_t ch = GetCodePointFromUTF8String(txt, i, &chrLen); 85 SPAssert(chrLen > 0); 86 i += chrLen; 87 if (ch >= static_cast<uint32_t>(glyphs.size())) { 88 goto fallback; 89 } 90 91 if (ch == 13 || ch == 10) { 92 // new line 93 x = 0.f; 94 h += (float)glyphHeight; 95 continue; 96 } 97 98 { 99 const GlyphInfo &info = glyphs[ch]; 100 101 if (info.type == Invalid) 102 goto fallback; 103 else if (info.type == Space) { 104 x += spaceWidth; 105 } else if (info.type == Image) { 106 x += info.advance; 107 } 108 109 if (x > w) { 110 w = x; 111 } 112 } 113 114 continue; 115 fallback: 116 x += MeasureFallback(ch, yMax - yMin); 117 if (x > w) { 118 w = x; 119 } 120 } 121 return MakeVector2(w, h); 122 } 123 Draw(const std::string & txt,spades::Vector2 offset,float scale,spades::Vector4 color)124 void Quake3Font::Draw(const std::string &txt, spades::Vector2 offset, float scale, 125 spades::Vector4 color) { 126 float x = 0.f, y = 0; 127 128 if (scale == 1.f) { 129 offset.x = floorf(offset.x); 130 offset.y = floorf(offset.y); 131 } 132 133 float a = color.w; 134 color.w = 1.f; 135 color *= a; 136 renderer->SetColorAlphaPremultiplied(color); 137 138 float invScale = 1.f / scale; 139 140 for (size_t i = 0; i < txt.size();) { 141 size_t chrLen = 0; 142 uint32_t ch = GetCodePointFromUTF8String(txt, i, &chrLen); 143 SPAssert(chrLen > 0); 144 i += chrLen; 145 if (ch >= static_cast<uint32_t>(glyphs.size())) { 146 goto fallback; 147 } 148 149 if (ch == 13 || ch == 10) { 150 // new line 151 x = 0.f; 152 y += (float)glyphHeight; 153 continue; 154 } 155 156 { 157 const GlyphInfo &info = glyphs[ch]; 158 159 if (info.type == Invalid) 160 goto fallback; 161 else if (info.type == Space) { 162 x += spaceWidth; 163 } else if (info.type == Image) { 164 AABB2 rt(x * scale + offset.x, y * scale + offset.y, 165 info.imageRect.GetWidth() * scale, 166 info.imageRect.GetHeight() * scale); 167 renderer->DrawImage(tex, rt, info.imageRect); 168 x += info.advance; 169 } 170 } 171 continue; 172 fallback: 173 DrawFallback(ch, MakeVector2(x, y + yMin) * scale + offset, (yMax - yMin) * scale, 174 color); 175 x += MeasureFallback(ch, (yMax - yMin) * scale) * invScale; 176 } 177 } 178 } 179 } 180