X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fvideo%2Ffont.cpp;h=7628f673e0f6ab1e84f7063ce6afca06981f5eac;hb=472d0ad804844d28811c86f03da74b6d6be53f1b;hp=db0633eedcec8d82263c9c2e954862bf5d0ab3f0;hpb=a99e13623a367ffcd0a4f125d16f90b928237f34;p=supertux.git diff --git a/src/video/font.cpp b/src/video/font.cpp index db0633eed..7628f673e 100644 --- a/src/video/font.cpp +++ b/src/video/font.cpp @@ -31,6 +31,7 @@ #include "lisp/lisp.hpp" #include "screen.hpp" #include "font.hpp" +#include "renderer.hpp" #include "drawing_context.hpp" #include "log.hpp" @@ -89,14 +90,14 @@ bool vline_empty(SDL_Surface* surface, int x, int start_y, int end_y, Uint8 thre } } // namespace -Font::Font(GlyphWidth glyph_width_, - const std::string& filename, +Font::Font(GlyphWidth glyph_width_, + const std::string& filename, const std::string& shadowfile, int char_width, int char_height_, int shadowsize_) : glyph_width(glyph_width_), - glyph_surface(0), shadow_glyph_surface(0), - char_height(char_height_), + glyph_surface(0), shadow_glyph_surface(0), + char_height(char_height_), shadowsize(shadowsize_) { glyph_surface = new Surface(filename); @@ -111,7 +112,7 @@ Font::Font(GlyphWidth glyph_width_, { float x = (i % 16) * char_width; float y = (i / 16) * char_height; - + Glyph glyph; glyph.advance = char_width; glyph.offset = Vector(0, 0); @@ -144,7 +145,7 @@ Font::Font(GlyphWidth glyph_width_, left += 1; int right = x + char_width - 1; - while (right > left && + while (right > left && vline_empty(surface, right, y, y + char_height, 64)) right -= 1; @@ -161,7 +162,7 @@ Font::Font(GlyphWidth glyph_width_, glyphs.push_back(glyph); shadow_glyphs.push_back(glyph); } - + SDL_UnlockSurface(surface); SDL_FreeSurface(surface); @@ -201,7 +202,7 @@ float Font::get_text_height(const std::string& text) const { std::string::size_type text_height = char_height; - + for(std::string::const_iterator it = text.begin(); it != text.end(); ++it) { // since UTF8 multibyte characters are decoded with values // outside the ASCII range there is no risk of overlapping and @@ -216,7 +217,7 @@ Font::get_text_height(const std::string& text) const float Font::get_height() const { - return char_height; + return char_height; } std::string @@ -241,9 +242,36 @@ Font::wrap_to_chars(const std::string& s, int line_length, std::string* overflow return s; } +std::string +Font::wrap_to_width(const std::string& s_, float width, std::string* overflow) +{ + std::string s = s_; + + // if text is already smaller, return full text + if (get_text_width(s) <= width) { + if (overflow) *overflow = ""; + return s; + } + + // if we can find a whitespace character to break at, return text up to this character + for (int i = s.length()-1; i >= 0; i--) { + std::string s2 = s.substr(0,i); + if (s[i] != ' ') continue; + if (get_text_width(s2) <= width) { + if (overflow) *overflow = s.substr(i+1); + return s.substr(0, i); + } + } + + // FIXME: hard-wrap at width, taking care of multibyte characters + if (overflow) *overflow = ""; + return s; +} + void -Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment, - DrawingEffect drawing_effect, float alpha) const +Font::draw(Renderer *renderer, const std::string& text, const Vector& pos_, + FontAlignment alignment, DrawingEffect drawing_effect, + float alpha) const { float x = pos_.x; float y = pos_.y; @@ -257,29 +285,29 @@ Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment, // calculate X positions based on the alignment type Vector pos = Vector(x, y); - + if(alignment == ALIGN_CENTER) pos.x -= get_text_width(temp) / 2; else if(alignment == ALIGN_RIGHT) pos.x -= get_text_width(temp); - + // Cast font position to integer to get a clean drawing result and // no bluring as we would get with subpixel positions pos.x = static_cast(pos.x); - draw_text(temp, pos, drawing_effect, alpha); + draw_text(renderer, temp, pos, drawing_effect, alpha); if (i == text.size()) break; - y += char_height + 2; + y += char_height + 2; last = i + 1; } } } void -Font::draw_text(const std::string& text, const Vector& pos, +Font::draw_text(Renderer *renderer, const std::string& text, const Vector& pos, DrawingEffect drawing_effect, float alpha) const { if(shadowsize > 0) @@ -287,18 +315,18 @@ Font::draw_text(const std::string& text, const Vector& pos, // FIXME: shadow_glyph_surface and glyph_surface do currently // share the same glyph array, this is incorrect and should be // fixed, it is however hardly noticable - draw_chars(shadow_glyph_surface, text, pos + Vector(shadowsize, shadowsize), - drawing_effect, alpha); + draw_chars(renderer, shadow_glyph_surface, text, + pos + Vector(shadowsize, shadowsize), drawing_effect, alpha); } - draw_chars(glyph_surface, text, pos, drawing_effect, alpha); + draw_chars(renderer, glyph_surface, text, pos, drawing_effect, alpha); } int Font::chr2glyph(uint32_t chr) const { int glyph_index = chr - first_char; - + // we don't have the control chars 0x80-0xa0 in the font if (chr >= 0x80) { // non-ascii character glyph_index -= 32; @@ -312,13 +340,14 @@ Font::chr2glyph(uint32_t chr) const log_debug << "Unsupported utf-8 character found" << std::endl; glyph_index = 0; } - + return glyph_index; } void -Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos, - DrawingEffect drawing_effect, float alpha) const +Font::draw_chars(Renderer *renderer, Surface* pchars, const std::string& text, + const Vector& pos, DrawingEffect drawing_effect, + float alpha) const { Vector p = pos; @@ -326,24 +355,32 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos, { int font_index = chr2glyph(*it); - if(*it == '\n') - { + if(*it == '\n') + { p.x = pos.x; p.y += char_height + 2; } - else if(*it == ' ') + else if(*it == ' ') { p.x += glyphs[font_index].advance; - } - else + } + else { const Glyph& glyph = glyphs[font_index]; - pchars->draw_part(glyph.rect.get_left(), - glyph.rect.get_top(), - p.x + glyph.offset.y, - p.y + glyph.offset.y, - glyph.rect.get_width(), glyph.rect.get_height(), - alpha, drawing_effect); + DrawingRequest request; + + request.pos = p + glyph.offset; + request.drawing_effect = drawing_effect; + request.alpha = alpha; + + SurfacePartRequest surfacepartrequest; + surfacepartrequest.size = glyph.rect.p2 - glyph.rect.p1; + surfacepartrequest.source = glyph.rect.p1; + surfacepartrequest.surface = pchars; + + request.request_data = &surfacepartrequest; + renderer->draw_surface_part(request); + p.x += glyphs[font_index].advance; } }