wesnoth-cvs-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Wesnoth-cvs-commits] wesnoth/src font.cpp language.hpp language.cpp


From: Jon Daniel
Subject: [Wesnoth-cvs-commits] wesnoth/src font.cpp language.hpp language.cpp
Date: Wed, 02 Mar 2005 09:18:39 -0500

CVSROOT:        /cvsroot/wesnoth
Module name:    wesnoth
Branch:         
Changes by:     Jon Daniel <address@hidden>     05/03/02 14:18:39

Modified files:
        src            : font.cpp language.hpp language.cpp 

Log message:
        * Changed the text_chunk to contain a UTF-8 string instead of a UCS4
        string
        * Updated split text to convert UTF-8 to UCS4 to look up the subset id
        and add UTF-8 strings to the text_chunk in the same loop.
        * Changed some text_surface inspectors to be public.
        * Changed text_surface::measure to use TTF_SizeUTF8
        * Changed text_surface::get_surfaces to use TTF_RenderUTF8_Blended
        * Changed text_surface::equal to text_surface::equals and let it use
        operator==(const SDL_Color&, const SDL_Color&)
        * Moved byte_size_from_utf8_first out of the anonymous namespace and
        added a prototype in language hpp.
        * Moved the invalid_utf8_exception to language.hpp
        
        I think all the character encoding string conversion functions should
        be moved to serialization/string_utils.

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/font.cpp.diff?tr1=1.107&tr2=1.108&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/language.hpp.diff?tr1=1.30&tr2=1.31&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/language.cpp.diff?tr1=1.71&tr2=1.72&r1=text&r2=text

Patches:
Index: wesnoth/src/font.cpp
diff -u wesnoth/src/font.cpp:1.107 wesnoth/src/font.cpp:1.108
--- wesnoth/src/font.cpp:1.107  Tue Mar  1 21:12:42 2005
+++ wesnoth/src/font.cpp        Wed Mar  2 14:18:38 2005
@@ -1,4 +1,4 @@
-/* $Id: font.cpp,v 1.107 2005/03/01 21:12:42 gruikya Exp $ */
+/* $Id: font.cpp,v 1.108 2005/03/02 14:18:38 j_daniel Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -64,51 +64,75 @@
 
 struct text_chunk
 {
-       text_chunk(subset_id subset, const wide_string& text) : subset(subset), 
text(text) {};
+       text_chunk(subset_id subset, const std::string& text) : subset(subset), 
text(text) {};
 
        subset_id subset;
-       wide_string text;
+       std::string text;
 };
 
 std::vector<subset_id> font_map;
 
-//Splits the text into chunks of text using the same font.
-std::vector<text_chunk> split_text(wide_string text)
-{
-       wide_string current_chunk;
-       std::vector<text_chunk> res;
+//Splits the UTF-8 text into chunks of UTF-8 text using the same font.
+//Converts UTF-8 bytes into one wchar_t at a time and gets the subset
+//id for it. The correspondending UTF-8 bytes then are appended to a 
+//chunk.
+std::vector<text_chunk> split_text(const std::string& utf8_text) {
        bool first = true;
        int current_font = 0;
+       std::string current_chunk;
+       std::vector<text_chunk> chunks;
+       
+       try {
+               size_t i = 0;
+               while(i < utf8_text.size()) {
+                       wchar_t ch = (unsigned char)utf8_text[i];
+                       const int num_bytes = byte_size_from_utf8_first(ch);
+
+                       if(i + num_bytes > utf8_text.size()) {
+                               throw invalid_utf8_exception();
+                       }
 
-       for(wide_string::const_iterator itor = text.begin(); itor != 
text.end(); ++itor) {
+                       if(num_bytes != 1) {
+                               ch &= 0xFF >> (num_bytes + 1);
+                       }
 
-               if(first) {
-                       if(*itor < font_map.size() && font_map[*itor] >= 0) {
-                               current_font = font_map[*itor];
+                       for(size_t j = i + 1; j != i + num_bytes; ++j) {
+                               const unsigned char ch2 = utf8_text[j];
+                               if((ch2 & 0xC0) != 0x80) {
+                                       throw invalid_utf8_exception();
+                               }
+                               ch = (ch << 6) | (ch2 & 0x3F);
+                       }
+                       
+                       if(first) {
+                               if(ch < font_map.size() && font_map[ch] >= 0) {
+                                       current_font = font_map[ch];
+                               } else {
+                                       current_font = 0;
+                               }
+                               first = false;
+                       }
+                       
+                       if(ch >= font_map.size() || font_map[ch] < 0) {
+                               current_chunk.append(utf8_text, i, num_bytes);
+                       } else if(font_map[ch] == current_font) {
+                               current_chunk.append(utf8_text, i, num_bytes);
                        } else {
-                               current_font = 0;
+                               chunks.push_back(text_chunk(current_font, 
current_chunk));
+                               current_chunk.clear();
+                               current_chunk.append(utf8_text, i, num_bytes);
+                               current_font = font_map[ch];
                        }
-                       first = false;
+                       i += num_bytes;
                }
-
-               // If the current character is outside the text map, we do not
-               // know how to do about it. So, just push it into the current
-               // chunk.
-               if(*itor >= font_map.size() || font_map[*itor] < 0) {
-                       current_chunk.push_back(*itor);
-               } else if(font_map[*itor] == current_font) {
-                       current_chunk.push_back(*itor);
-               } else {
-                       res.push_back(text_chunk(current_font, current_chunk));
-                       current_chunk.clear();
-                       current_chunk.push_back(*itor);
-                       current_font = font_map[*itor];
+               if (!current_chunk.empty()) {
+                       chunks.push_back(text_chunk(current_font, 
current_chunk));
                }
        }
-       if (!current_chunk.empty()) {
-               res.push_back(text_chunk(current_font, current_chunk));
+       catch(invalid_utf8_exception e) {
+               WRN_FT << "Invalid UTF-8 string: \"" << utf8_text << "\"\n";
        }
-       return res;
+       return chunks;
 }
 
 TTF_Font* open_font(const std::string& fname, int size)
@@ -312,11 +336,15 @@
        text_surface(std::string const &str, int size, SDL_Color color, int 
style);
        text_surface(int size, SDL_Color color, int style);
        void set_text(std::string const &str);
-       bool operator==(text_surface const &t) const { return hash_ == t.hash_ 
&& equal(t); }
-       bool operator!=(text_surface const &t) const { return hash_ != t.hash_ 
|| !equal(t); }
+
+       void measure() const;
        size_t width() const;
        size_t height() const;
        std::vector<surface> const & get_surfaces() const;
+
+       bool equals(text_surface const &t) const;
+       bool operator==(text_surface const &t) const { return hash_ == t.hash_ 
&& equals(t); }
+       bool operator!=(text_surface const &t) const { return hash_ != t.hash_ 
|| !equals(t); }
 private:
        int hash_;
        int font_size_;
@@ -327,8 +355,6 @@
        mutable std::vector<surface> surfs_;
        mutable bool initialized_;
        void hash();
-       void measure() const;
-       bool equal(text_surface const &t) const;
 };
 
 text_surface::text_surface(std::string const &str, int size, SDL_Color color, 
int style)
@@ -345,6 +371,7 @@
 void text_surface::set_text(std::string const &str)
 {
        str_ = str;
+       initialized_ = false;
        hash();
 }
 
@@ -356,10 +383,10 @@
        hash_ = h;
 }
 
-bool text_surface::equal(text_surface const &t) const
+bool text_surface::equals(text_surface const &t) const
 {
        return font_size_ == t.font_size_
-               && color_.r == t.color_.r && color_.g == t.color_.g && color_.b 
== t.color_.b
+               && color_ == t.color_
                && style_ == t.style_
                && str_ == t.str_;
 }
@@ -369,8 +396,7 @@
        w_ = 0;
        h_ = 0;
        
-       wide_string ws = string_to_wstring(str_);
-       std::vector<text_chunk> substrings = split_text(ws);
+       std::vector<text_chunk> substrings = split_text(str_);
 
        for(std::vector<text_chunk>::const_iterator itor = substrings.begin(); 
                        itor != substrings.end(); ++itor) {
@@ -380,19 +406,10 @@
                        continue;
                font_style_setter const style_setter(ttfont, style_);
 
-               //Convert the wide_string into something usable by sdl_ttf.
-               //This is pretty ugly.
-               util::scoped_array<Uint16> text(new Uint16[itor->text.size() + 
1]);
-               wide_string::const_iterator c = itor->text.begin();
-               int i;
-               for(i = 0; c != itor->text.end(); ++c, ++i)
-                       text[i] = *c;
-               text[i] = 0;
-
                int w;
                int h;
 
-               TTF_SizeUNICODE(ttfont, text, &w, &h);
+               TTF_SizeUTF8(ttfont, itor->text.c_str(), &w, &h);
                w_ += w;
                h_ = maximum<int>(h_, h);
        }
@@ -424,8 +441,7 @@
        if(width() > max_text_line_width)
                return surfs_;
 
-       wide_string ws = string_to_wstring(str_);
-       std::vector<text_chunk> substrings = split_text(ws);
+       std::vector<text_chunk> substrings = split_text(str_);
 
        for(std::vector<text_chunk>::const_iterator itor = substrings.begin(); 
                        itor != substrings.end(); ++itor) {
@@ -434,16 +450,7 @@
                        continue;
                font_style_setter const style_setter(ttfont, style_);
 
-               //Convert the wide_string into something usable by sdl_ttf.
-               //This is pretty ugly.
-               util::scoped_array<Uint16> text(new Uint16[itor->text.size() + 
1]);
-               wide_string::const_iterator c = itor->text.begin();
-               int i;
-               for(i = 0; c != itor->text.end(); ++c, ++i)
-                       text[i] = *c;
-               text[i] = 0;
-
-               surface s = surface(TTF_RenderUNICODE_Blended(ttfont, text, 
color_));
+               surface s = surface(TTF_RenderUTF8_Blended(ttfont, 
itor->text.c_str(), color_));
                if(!s.null())
                        surfs_.push_back(s);
        }
Index: wesnoth/src/language.cpp
diff -u wesnoth/src/language.cpp:1.71 wesnoth/src/language.cpp:1.72
--- wesnoth/src/language.cpp:1.71       Sun Feb 27 12:14:59 2005
+++ wesnoth/src/language.cpp    Wed Mar  2 14:18:38 2005
@@ -1,4 +1,4 @@
-/* $Id: language.cpp,v 1.71 2005/02/27 12:14:59 ydirson Exp $ */
+/* $Id: language.cpp,v 1.72 2005/03/02 14:18:38 j_daniel Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -209,9 +209,6 @@
        return known_languages[0];
 }
 
-class invalid_utf8_exception : public std::exception {
-};
-
 namespace 
 {
 std::string wstring_to_utf8(const wide_string &src)
@@ -265,28 +262,6 @@
        }
 }
 
-int byte_size_from_utf8_first(unsigned char ch)
-{
-       int count;
-
-       if ((ch & 0x80) == 0)
-               count = 1;
-       else if ((ch & 0xE0) == 0xC0)
-               count = 2;
-       else if ((ch & 0xF0) == 0xE0)
-               count = 3;
-       else if ((ch & 0xF8) == 0xF0)
-               count = 4;
-       else if ((ch & 0xFC) == 0xF8)
-               count = 5;
-       else if ((ch & 0xFE) == 0xFC)
-               count = 6;
-       else
-               throw invalid_utf8_exception(); /* stop on invalid characters */
-
-       return count;
-}
-       
 wide_string utf8_to_wstring(const std::string &src)
 {
        wide_string ret;        
@@ -327,6 +302,28 @@
 
 }
 
+int byte_size_from_utf8_first(unsigned char ch)
+{
+       int count;
+
+       if ((ch & 0x80) == 0)
+               count = 1;
+       else if ((ch & 0xE0) == 0xC0)
+               count = 2;
+       else if ((ch & 0xF0) == 0xE0)
+               count = 3;
+       else if ((ch & 0xF8) == 0xF0)
+               count = 4;
+       else if ((ch & 0xFC) == 0xF8)
+               count = 5;
+       else if ((ch & 0xFE) == 0xFC)
+               count = 6;
+       else
+               throw invalid_utf8_exception(); /* stop on invalid characters */
+
+       return count;
+}
+
 std::vector<std::string> split_utf8_string(const std::string &src)
 {
        std::vector<std::string> ret;
Index: wesnoth/src/language.hpp
diff -u wesnoth/src/language.hpp:1.30 wesnoth/src/language.hpp:1.31
--- wesnoth/src/language.hpp:1.30       Tue Nov 30 21:41:18 2004
+++ wesnoth/src/language.hpp    Wed Mar  2 14:18:38 2005
@@ -1,4 +1,4 @@
-/* $Id: language.hpp,v 1.30 2004/11/30 21:41:18 silene Exp $ */
+/* $Id: language.hpp,v 1.31 2005/03/02 14:18:38 j_daniel Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -67,6 +67,9 @@
 
 //functions for converting Unicode wide-char strings to UTF-8 encoded
 //strings, back and forth
+class invalid_utf8_exception : public std::exception {
+};
+int byte_size_from_utf8_first(unsigned char ch);
 std::vector<std::string> split_utf8_string(const std::string &src);
 std::string wstring_to_string(const wide_string &);
 wide_string string_to_wstring(const std::string &);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]