00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #if defined(HAVE_SDL_SDL_TTF_H)
00022 #include <SDL/SDL_ttf.h>
00023 #else
00024 #include "SDL_ttf.h"
00025 #endif
00026
00027 #include "RenderSurface.h"
00028 #include "TTFont.h"
00029 #include "TTFRenderedText.h"
00030 #include "Texture.h"
00031 #include "IDataSource.h"
00032 #include "encoding.h"
00033
00034 #include <iomanip>
00035
00036 DEFINE_RUNTIME_CLASSTYPE_CODE(TTFont,Pentagram::Font);
00037
00038
00039 static const Uint16 bullets[] = { 0x2022, 0x30FB, 0x25CF, 0 };
00040
00041
00042 TTFont::TTFont(TTF_Font* font, uint32 rgb_, int bordersize_,
00043 bool antiAliased_, bool SJIS_)
00044 : ttf_font(font), antiAliased(antiAliased_), SJIS(SJIS_)
00045 {
00046
00047
00048 rgb = (rgb_>>16)&0xFF | ((rgb_>>8)&0xFF)<<8 | (rgb_&0xFF)<<16;
00049 bordersize = bordersize_;
00050
00051 bullet = 0;
00052
00053 for (int i = 0; bullets[i]; ++i) {
00054 int minx, maxx, miny, maxy;
00055 if (TTF_GlyphMetrics(font, bullets[i], &minx, &maxx,
00056 &miny, &maxy, 0) == 0) {
00057 if ((minx != 0 || maxx != 0) && (miny != 0 || maxy != 0)) {
00058 bullet = bullets[i];
00059 break;
00060 }
00061 }
00062 }
00063 if (bullet == 0) {
00064 bullet = '*';
00065 }
00066 }
00067
00068 TTFont::~TTFont()
00069 {
00070
00071 }
00072
00073 int TTFont::getHeight()
00074 {
00075 return TTF_FontHeight(ttf_font) + 2*bordersize;
00076 }
00077
00078 int TTFont::getBaseline()
00079 {
00080 return TTF_FontAscent(ttf_font);
00081 }
00082
00083 int TTFont::getBaselineSkip()
00084 {
00085 return TTF_FontLineSkip(ttf_font);
00086 }
00087
00088
00089 template<class T>
00090 static uint16* toUnicode(const std::string& text, uint16 bullet)
00091 {
00092 std::string::size_type l = T::length(text);
00093 uint16* unicodetext = new uint16[l+1];
00094 std::string::const_iterator iter = text.begin();
00095 for (unsigned int i = 0; i < l; ++i) {
00096 uint32 u = T::unicode(iter);
00097 if (u > 0xFFFF) {
00098 perr.printf("Warning: unicode character out of range for SDL_ttf: %x\n", u);
00099 unicodetext[i] = '?';
00100 } else if (u == 64) {
00101 unicodetext[i] = bullet;
00102 } else {
00103 unicodetext[i] = u;
00104 }
00105 }
00106 unicodetext[l] = 0;
00107 return unicodetext;
00108 }
00109
00110
00111 void TTFont::getStringSize(const std::string& text, int& width, int& height)
00112 {
00113
00114 uint16* unicodetext;
00115 if (!SJIS)
00116 unicodetext = toUnicode<Traits>(text, bullet);
00117 else
00118 unicodetext = toUnicode<SJISTraits>(text, bullet);
00119
00120 TTF_SizeUNICODE(ttf_font, unicodetext, &width, &height);
00121 delete[] unicodetext;
00122 #if 0
00123 pout << "StringSize: " << width << "," << height << ": " << text << std::endl;
00124 pout << "height: " << TTF_FontHeight(ttf_font) << std::endl;
00125 pout << "lineskip: " << TTF_FontLineSkip(ttf_font) << std::endl;
00126 pout << "ascent: " << TTF_FontAscent(ttf_font) << std::endl;
00127 pout << "descent: " << TTF_FontDescent(ttf_font) << std::endl;
00128 #endif
00129
00130 width += 2*bordersize;
00131 height += 2*bordersize;
00132 }
00133
00134 void TTFont::getTextSize(const std::string& text,
00135 int& resultwidth, int& resultheight,
00136 unsigned int& remaining,
00137 int width, int height, TextAlign align,
00138 bool u8specials)
00139 {
00140 std::list<PositionedText> tmp;
00141 if (!SJIS)
00142 tmp = typesetText<Traits>(this, text, remaining,
00143 width, height, align, u8specials,
00144 resultwidth, resultheight);
00145 else
00146 tmp = typesetText<SJISTraits>(this, text, remaining,
00147 width, height, align, u8specials,
00148 resultwidth, resultheight);
00149 }
00150
00151
00152 RenderedText* TTFont::renderText(const std::string& text,
00153 unsigned int& remaining,
00154 int width, int height,
00155 TextAlign align, bool u8specials,
00156 std::string::size_type cursor)
00157 {
00158 int resultwidth, resultheight;
00159 std::list<PositionedText> lines;
00160 if (!SJIS)
00161 lines = typesetText<Traits>(this, text, remaining,
00162 width, height, align, u8specials,
00163 resultwidth, resultheight, cursor);
00164 else
00165 lines = typesetText<SJISTraits>(this, text, remaining,
00166 width, height, align, u8specials,
00167 resultwidth, resultheight, cursor);
00168
00169
00170 uint32* buf = new uint32[resultwidth*resultheight];
00171 memset(buf, 0, 4*resultwidth*resultheight);
00172
00173 Texture* texture = new Texture;
00174 texture->buffer = buf;
00175 texture->width = resultwidth;
00176 texture->height = resultheight;
00177
00178 #if 0
00179 pout << "Total size: " << resultwidth << "," << resultheight << std::endl;
00180 #endif
00181
00182 std::list<PositionedText>::iterator iter;
00183 for (iter = lines.begin(); iter != lines.end(); ++iter)
00184 {
00185
00186 uint16* unicodetext;
00187 if (!SJIS)
00188 unicodetext = toUnicode<Traits>(iter->text, bullet);
00189 else
00190 unicodetext = toUnicode<SJISTraits>(iter->text, bullet);
00191
00192
00193 SDL_Surface* textsurf;
00194
00195 if (!antiAliased)
00196 {
00197 SDL_Color white = { 0xFF , 0xFF , 0xFF, 0 };
00198 textsurf = TTF_RenderUNICODE_Solid(ttf_font, unicodetext, white);
00199 }
00200 else
00201 {
00202 SDL_Color colour = { TEX32_R(rgb) , TEX32_G(rgb), TEX32_B(rgb), 0 };
00203 SDL_Color black = { 0x00 , 0x00 , 0x00, 0 };
00204 textsurf = TTF_RenderUNICODE_Shaded(ttf_font, unicodetext, colour, black);
00205 }
00206
00207 if (textsurf) {
00208 SDL_LockSurface(textsurf);
00209
00210 #if 0
00211 pout << iter->dims.w << "," << iter->dims.h << " vs. "
00212 << textsurf->w << "," << textsurf->h << ": " << iter->text
00213 << std::endl;
00214 #endif
00215 SDL_Palette *pal = textsurf->format->palette;
00216
00217
00218 for (int y = 0; y < textsurf->h; y++) {
00219 uint8* surfrow = static_cast<uint8*>(textsurf->pixels) + y * textsurf->pitch;
00220
00221 uint32* bufrow = buf + (iter->dims.y+y+bordersize)*resultwidth;
00222 for (int x = 0; x < textsurf->w; x++) {
00223
00224 if (!antiAliased && surfrow[x] == 1) {
00225
00226 bufrow[iter->dims.x+x+bordersize] = rgb | 0xFF000000;
00227 if (bordersize <= 0) continue;
00228 if (bordersize == 1) {
00229
00230 for (int dx = -1; dx <= 1; dx++) {
00231 for (int dy = -1; dy <= 1; dy++) {
00232 if (x + 1 + iter->dims.x + dx >= 0 &&
00233 x + 1 + iter->dims.x + dx < resultwidth &&
00234 y + 1 + dy >= 0 && y + 1 + dy < resultheight)
00235 {
00236 if (buf[(y+iter->dims.y+dy+1)*resultwidth + x+1+iter->dims.x+dx] == 0) {
00237 buf[(y+iter->dims.y+dy+1)*resultwidth + x+1+iter->dims.x+dx] = 0xFF000000;
00238 }
00239 }
00240 }
00241 }
00242 continue;
00243 }
00244 for (int dx = -bordersize; dx <= bordersize; dx++) {
00245 for (int dy = -bordersize; dy <= bordersize; dy++) {
00246 if (x + bordersize + iter->dims.x + dx >= 0 &&
00247 x + bordersize + iter->dims.x + dx < resultwidth &&
00248 y + bordersize + dy >= 0 && y + bordersize + dy < resultheight)
00249 {
00250 if (buf[(y+iter->dims.y+dy+bordersize)*resultwidth + x+bordersize+iter->dims.x+dx] == 0) {
00251 buf[(y+iter->dims.y+dy+bordersize)*resultwidth + x+bordersize+iter->dims.x+dx] = 0xFF000000;
00252 }
00253 }
00254 }
00255 }
00256 }
00257 else if (antiAliased)
00258 {
00259 uint32 idx = surfrow[x];
00260
00261 if (idx == 0) continue;
00262 SDL_Color pe = pal->colors[idx];
00263
00264 if (bordersize <= 0) {
00265 bufrow[iter->dims.x+x+bordersize] = TEX32_PACK_RGBA(pe.r, pe.g, pe.b, idx);
00266 }
00267 else {
00268 bufrow[iter->dims.x+x+bordersize] = TEX32_PACK_RGBA(pe.r, pe.g, pe.b, 0xFF);
00269
00270
00271 if (bordersize == 1) for (int dx = -1; dx <= 1; dx++) {
00272 for (int dy = -1; dy <= 1; dy++) {
00273 if (x + 1 + iter->dims.x + dx >= 0 &&
00274 x + 1 + iter->dims.x + dx < resultwidth &&
00275 y + 1 + dy >= 0 && y + 1 + dy < resultheight)
00276 {
00277 uint32 alpha = TEX32_A(buf[(y+iter->dims.y+dy+1)*resultwidth + x+1+iter->dims.x+dx]);
00278 if (alpha != 0xFF) {
00279 alpha = 255-(((255-alpha) * (255-idx))>>8);
00280 buf[(y+iter->dims.y+dy+1)*resultwidth + x+1+iter->dims.x+dx] = alpha<<TEX32_A_SHIFT;
00281 }
00282 }
00283 }
00284 }
00285 else for (int dx = -bordersize; dx <= bordersize; dx++) {
00286 for (int dy = -bordersize; dy <= bordersize; dy++) {
00287 if (x + bordersize + iter->dims.x + dx >= 0 &&
00288 x + bordersize + iter->dims.x + dx < resultwidth &&
00289 y + bordersize + dy >= 0 && y + bordersize + dy < resultheight)
00290 {
00291 uint32 alpha = TEX32_A(buf[(y+iter->dims.y+dy+bordersize)*resultwidth + x+bordersize+iter->dims.x+dx]);
00292 if (alpha != 0xFF) {
00293 alpha = 255-(((255-alpha) * (255-idx))>>8);
00294 buf[(y+iter->dims.y+dy+bordersize)*resultwidth + x+bordersize+iter->dims.x+dx] = alpha<<TEX32_A_SHIFT;
00295 }
00296 }
00297 }
00298 }
00299 }
00300 }
00301 }
00302 }
00303
00304 SDL_UnlockSurface(textsurf);
00305 SDL_FreeSurface(textsurf);
00306 }
00307
00308 if (iter->cursor != std::string::npos) {
00309 int w, h;
00310 assert(iter->cursor <= iter->text.size());
00311 unicodetext[iter->cursor] = 0;
00312 TTF_SizeUNICODE(ttf_font, unicodetext,&w,&h);
00313 for (int y = 0; y < iter->dims.h; y++) {
00314 uint32* bufrow = buf + (iter->dims.y+y)*resultwidth;
00315 bufrow[iter->dims.x+w+bordersize] = 0xFF000000;
00316
00317
00318 }
00319 }
00320
00321 delete[] unicodetext;
00322
00323 }
00324
00325 return new TTFRenderedText(texture, resultwidth, resultheight,
00326 getBaselineSkip() - getHeight(), this);
00327 }