TextRubiFadeSurface.cpp is implemented.
@@ -85,11 +85,11 @@ | ||
85 | 85 | luabindGui.o: ../gui/EventUtils.h ../gui/LayerManager.h |
86 | 86 | luabindGui.o: ../gui/LayerInterface.h ../gui/Layer.h ../gui/Font.h |
87 | 87 | luabindGui.o: ../common/Color.h ../gui/TextSurface.h ../gui/Surface.h |
88 | -luabindGui.o: ../gui/TextFadeSurface.h ../gui/ColorSurface.h | |
89 | -luabindGui.o: ../gui/FillSurface.h ../gui/ImageSurface.h | |
90 | -luabindGui.o: ../gui/MultiSurface.h ../gui/Label.h ../gui/Component.h | |
91 | -luabindGui.o: ../gui/Button.h ../gui/Menu.h ../gui/ChatMessage.h | |
92 | -luabindGui.o: ../gui/CallbackEvent.h ../gui/AlignUtils.h | |
88 | +luabindGui.o: ../gui/TextFadeSurface.h ../gui/TextRubiFadeSurface.h | |
89 | +luabindGui.o: ../gui/ColorSurface.h ../gui/FillSurface.h | |
90 | +luabindGui.o: ../gui/ImageSurface.h ../gui/MultiSurface.h ../gui/Label.h | |
91 | +luabindGui.o: ../gui/Component.h ../gui/Button.h ../gui/Menu.h | |
92 | +luabindGui.o: ../gui/ChatMessage.h ../gui/CallbackEvent.h ../gui/AlignUtils.h | |
93 | 93 | luabindInit.o: luabindInit.h LuaHandler.h ../system/log_printf.h |
94 | 94 | luabindInput.o: luabindInput.h ../input/convertToRoman.h |
95 | 95 | luabindInput.o: ../input/convertToJp.h ../input/Utf8.h ../input/utf8_string.h |
@@ -5,32 +5,145 @@ | ||
5 | 5 | \author Satofumi KAMIMURA |
6 | 6 | |
7 | 7 | $Id$ |
8 | + | |
9 | + \todo ルビの指定を任意にして、TextFadeSurface を置き換える | |
10 | + \todo プロポーショナル・フォント以外でも動作するようにする | |
8 | 11 | */ |
9 | 12 | |
10 | 13 | #include "TextRubiFadeSurface.h" |
11 | 14 | #include "TextSurface.h" |
15 | +#include "TextFadeSurface.h" | |
12 | 16 | #include "Font.h" |
17 | +#include "Utf8.h" | |
18 | +#include "rubi_parse.h" | |
19 | +#include <vector> | |
13 | 20 | |
14 | 21 | using namespace qrk; |
22 | +using namespace std; | |
15 | 23 | |
16 | 24 | |
25 | +namespace | |
26 | +{ | |
27 | + enum { | |
28 | + FadeWidthPixel = 200, | |
29 | + }; | |
30 | + | |
31 | + | |
32 | + typedef vector<TextSurface*> Surfaces; | |
33 | +} | |
34 | + | |
35 | + | |
17 | 36 | struct TextRubiFadeSurface::pImpl |
18 | 37 | { |
38 | + TextFadeSurface text_; | |
39 | + Surfaces rubi_text_; | |
40 | + vector<int> rubi_x_; | |
19 | 41 | Rect<long> rect_; |
42 | + int rubi_pixel_size_; | |
43 | + float base_alpha_; | |
44 | + size_t percent_; | |
20 | 45 | |
21 | 46 | |
22 | 47 | pImpl(const Font& font, const char* text, |
23 | 48 | const Font& rubi_font, const char* kana_only_text) |
49 | + : text_(font, text), | |
50 | + rect_(0, 0, text_.rect().w, text_.rect().h + rubi_font.pixelSize()), | |
51 | + rubi_pixel_size_(rubi_font.pixelSize()), base_alpha_(1.0), | |
52 | + percent_(100) | |
24 | 53 | { |
25 | - (void)font; | |
26 | - (void)text; | |
27 | - (void)rubi_font; | |
28 | - (void)kana_only_text; | |
54 | + vector<rubi_t> rubi_positions; | |
55 | + rubi_parse(rubi_positions, text, kana_only_text); | |
29 | 56 | |
30 | - // !!! | |
57 | + // ルビの文字サーフェスを作成 | |
58 | + int kanji_pixel_size = font.pixelSize(); | |
59 | + Utf8 kana_only(kana_only_text); | |
60 | + for (vector<rubi_t>::const_iterator it = rubi_positions.begin(); | |
61 | + it != rubi_positions.end(); ++it) { | |
31 | 62 | |
32 | - // !!! rect_ の初期化 | |
63 | + int kanji_size = kanji_pixel_size * it->kanji_size; | |
64 | + int rubi_size = rubi_pixel_size_ * it->rubi_size; | |
65 | + int rubi_space = max(kanji_size - rubi_size, 0); | |
66 | + int rubi_space_each = | |
67 | + (it->rubi_size > 1) ? rubi_space / it->rubi_size : 0; | |
68 | + rubi_size += it->rubi_size * rubi_space_each; | |
69 | + int x_offset = (kanji_size - rubi_size) / 2; | |
70 | + int kanji_base_x = | |
71 | + kanji_pixel_size * it->kanji_first; | |
72 | + | |
73 | + for (size_t i = 0; i < it->rubi_size; ++i) { | |
74 | + const string rubi_ch = | |
75 | + kana_only.substr(it->rubi_first + i, 1).toStdString(); | |
76 | + TextSurface* surface = | |
77 | + new TextSurface(rubi_font, rubi_ch.c_str()); | |
78 | + rubi_text_.push_back(surface); | |
79 | + | |
80 | + // 漢字の位置の対応する位置に、ルビの文字を配置する | |
81 | + int x = kanji_base_x + x_offset | |
82 | + + ((rubi_pixel_size_ + rubi_space_each) * i); | |
83 | + rubi_x_.push_back(x); | |
84 | + } | |
85 | + } | |
33 | 86 | } |
87 | + | |
88 | + | |
89 | + ~pImpl(void) | |
90 | + { | |
91 | + for (Surfaces::iterator it = rubi_text_.begin(); | |
92 | + it != rubi_text_.end(); ++it) { | |
93 | + delete *it; | |
94 | + } | |
95 | + } | |
96 | + | |
97 | + | |
98 | + void setAlpha(void) | |
99 | + { | |
100 | + text_.setFadePercent(percent_); | |
101 | + | |
102 | + int moved_width = | |
103 | + static_cast<int>((rect_.w + FadeWidthPixel) * percent_ / 100.0); | |
104 | + int first = -FadeWidthPixel + moved_width; | |
105 | + int last = 0 + moved_width; | |
106 | + | |
107 | + size_t index = 0; | |
108 | + for (Surfaces::iterator it = rubi_text_.begin(); | |
109 | + it != rubi_text_.end(); ++it, ++index) { | |
110 | + Surface* surface = *it; | |
111 | + | |
112 | + float alpha = 1.0; | |
113 | + int x = rubi_x_[index]; | |
114 | + if (x > last) { | |
115 | + alpha = 0.0; | |
116 | + } else if (x <= first) { | |
117 | + alpha = 1.0; | |
118 | + } else { | |
119 | + alpha = (last - x) / static_cast<float>(FadeWidthPixel); | |
120 | + } | |
121 | + surface->setAlpha(alpha * base_alpha_); | |
122 | + x += surface->rect().w; | |
123 | + } | |
124 | + } | |
125 | + | |
126 | + | |
127 | + void draw(const Rect<long>* src, const Rect<long>* dest) | |
128 | + { | |
129 | + if (! text_.isValid()) { | |
130 | + return; | |
131 | + } | |
132 | + Rect<long> sub_dest(*dest); | |
133 | + sub_dest.y += rubi_pixel_size_; | |
134 | + text_.draw(src, &sub_dest); | |
135 | + | |
136 | + sub_dest.y -= rubi_pixel_size_; | |
137 | + int index = 0; | |
138 | + for (Surfaces::iterator it = rubi_text_.begin(); | |
139 | + it != rubi_text_.end(); ++it, ++index) { | |
140 | + Surface* surface = *it; | |
141 | + sub_dest.w = surface->rect().w; | |
142 | + sub_dest.h = surface->rect().h; | |
143 | + sub_dest.x = dest->x + rubi_x_[index]; | |
144 | + surface->draw(src, &sub_dest); | |
145 | + } | |
146 | + } | |
34 | 147 | }; |
35 | 148 | |
36 | 149 |
@@ -49,9 +162,8 @@ | ||
49 | 162 | |
50 | 163 | bool TextRubiFadeSurface::isValid(void) const |
51 | 164 | { |
52 | - // !!! フォントがなければ、false になるはず | |
53 | - // !!! 最初の surfaces_ の状態で判断してもよい | |
54 | - return true; | |
165 | + // ルビは表示されなくても valid だとみなす | |
166 | + return pimpl->text_.isValid(); | |
55 | 167 | } |
56 | 168 | |
57 | 169 |
@@ -63,16 +175,14 @@ | ||
63 | 175 | |
64 | 176 | void TextRubiFadeSurface::setAlpha(float alpha) |
65 | 177 | { |
66 | - (void)alpha; | |
67 | - // !!! | |
178 | + pimpl->base_alpha_ = alpha; | |
179 | + pimpl->setAlpha(); | |
68 | 180 | } |
69 | 181 | |
70 | 182 | |
71 | 183 | float TextRubiFadeSurface::alpha(void) const |
72 | 184 | { |
73 | - //pimpl->alpha_; | |
74 | - // !!! | |
75 | - return 1.0; | |
185 | + return pimpl->base_alpha_; | |
76 | 186 | } |
77 | 187 | |
78 | 188 |
@@ -85,14 +195,12 @@ | ||
85 | 195 | |
86 | 196 | void TextRubiFadeSurface::draw(const Rect<long>* src, const Rect<long>* dest) |
87 | 197 | { |
88 | - (void)src; | |
89 | - (void)dest; | |
90 | - // !!! | |
198 | + pimpl->draw(src, dest); | |
91 | 199 | } |
92 | 200 | |
93 | 201 | |
94 | 202 | void TextRubiFadeSurface::setFadePercent(size_t percent) |
95 | 203 | { |
96 | - (void)percent; | |
97 | - // !!! | |
204 | + pimpl->percent_ = min(percent, static_cast<size_t>(100)); | |
205 | + pimpl->setAlpha(); | |
98 | 206 | } |
@@ -120,6 +120,8 @@ | ||
120 | 120 | TextInput.o: TextInput.h Event.h ../geometry/Point.h LayerManager.h |
121 | 121 | TextInput.o: LayerInterface.h CallbackEvent.h ../geometry/Rect.h |
122 | 122 | TextRubiFadeSurface.o: TextRubiFadeSurface.h Surface.h ../geometry/Rect.h |
123 | -TextRubiFadeSurface.o: TextSurface.h Font.h ../common/Color.h | |
123 | +TextRubiFadeSurface.o: TextSurface.h TextFadeSurface.h Font.h | |
124 | +TextRubiFadeSurface.o: ../common/Color.h ../input/Utf8.h | |
125 | +TextRubiFadeSurface.o: ../input/rubi_parse.h | |
124 | 126 | TextSurface.o: TextSurface.h Surface.h ../geometry/Rect.h Font.h |
125 | 127 | TextSurface.o: ../common/Color.h SDL_GL_Texture.h |
@@ -0,0 +1,45 @@ | ||
1 | +/*! | |
2 | + \example rubiDraw.cpp | |
3 | + | |
4 | + \author Satofumi KAMIMURA | |
5 | + | |
6 | + $Id$ | |
7 | +*/ | |
8 | + | |
9 | +#include "Screen.h" | |
10 | +#include "Font.h" | |
11 | +#include "TextRubiFadeSurface.h" | |
12 | + | |
13 | +using namespace qrk; | |
14 | + | |
15 | + | |
16 | +int main(int argc, char *argv[]) | |
17 | +{ | |
18 | + Screen screen; | |
19 | + screen.show(SDL_OPENGL); | |
20 | + | |
21 | + // フォントの読み出し | |
22 | + const char* font_file = (argc <= 1) ? "font.ttf" : argv[1]; | |
23 | + Font font(font_file, 32); | |
24 | + Font rubi_font(font_file, 16); | |
25 | + | |
26 | + // ルビを含む文字列の描画 | |
27 | + TextRubiFadeSurface surface(font, "今日は、卵を食べました。", | |
28 | + rubi_font, "きょうは、たまごをたべました。"); | |
29 | + Rect<long> dest_rect = surface.rect(); | |
30 | + dest_rect.x += 100; | |
31 | + | |
32 | + // 描画した文字列のをフェードさせる | |
33 | + for (size_t j = 0; j < 1; ++j) { | |
34 | + for (size_t i = 0; i <= 100; ++i) { | |
35 | + screen.clear(); | |
36 | + surface.setFadePercent(i); | |
37 | + surface.draw(NULL, &dest_rect); | |
38 | + SDL_GL_SwapBuffers(); | |
39 | + SDL_Delay(10); | |
40 | + } | |
41 | + } | |
42 | + SDL_Delay(100); | |
43 | + | |
44 | + return 0; | |
45 | +} |
@@ -12,6 +12,7 @@ | ||
12 | 12 | |
13 | 13 | # Target |
14 | 14 | TARGET = \ |
15 | + rubiDraw \ | |
15 | 16 | canvasDraw \ |
16 | 17 | fadeText \ |
17 | 18 | simpleScreen \ |
@@ -43,7 +44,7 @@ | ||
43 | 44 | $(REQUIRE_LIBS) : |
44 | 45 | cd $(@D)/ && $(MAKE) $(@F) |
45 | 46 | |
46 | -PROGRAMS = drawText handleEvent inputDraw chatMessageSample rectMove buttonSample menuSample drawColorSurface fadeText canvasDraw | |
47 | +PROGRAMS = drawText handleEvent inputDraw chatMessageSample rectMove buttonSample menuSample drawColorSurface fadeText canvasDraw rubiDraw | |
47 | 48 | $(PROGRAMS) : $(REQUIRE_LIBS) |
48 | 49 | |
49 | 50 | # DO NOT DELETE |
@@ -86,3 +87,5 @@ | ||
86 | 87 | rectMove.o: ../../geometry/Point.h ../LayerManager.h ../LayerInterface.h |
87 | 88 | rectMove.o: ../Layer.h ../CallbackEvent.h ../Event.h ../EventUtils.h |
88 | 89 | rectMove.o: ../../system/delay.h |
90 | +rubiDraw.o: ../Screen.h ../../geometry/Rect.h ../Font.h ../../common/Color.h | |
91 | +rubiDraw.o: ../TextRubiFadeSurface.h ../Surface.h |
@@ -25,7 +25,7 @@ | ||
25 | 25 | } rubi_t; |
26 | 26 | |
27 | 27 | |
28 | - extern bool parse_rubi(std::vector<rubi_t>& rubi_positions, | |
28 | + extern bool rubi_parse(std::vector<rubi_t>& rubi_positions, | |
29 | 29 | const char* text, const char* kana_only); |
30 | 30 | } |
31 | 31 |
@@ -12,6 +12,8 @@ | ||
12 | 12 | #include "rubi_parse.h" |
13 | 13 | #include "Utf8.h" |
14 | 14 | |
15 | +#include <cstdio> | |
16 | + | |
15 | 17 | using namespace qrk; |
16 | 18 | using namespace std; |
17 | 19 |
@@ -116,8 +118,8 @@ | ||
116 | 118 | kana_offset + same_size, |
117 | 119 | rubi_size)); |
118 | 120 | |
119 | - size_t next_kanji_offset = kanji_offset + kana_index + 1; | |
120 | - size_t next_kana_offset = kana_offset + same_size + rubi_size + 1; | |
121 | + size_t next_kanji_offset = kana_index + 1; | |
122 | + size_t next_kana_offset = same_size + rubi_size + 1; | |
121 | 123 | const string next_kanji = |
122 | 124 | kanji.substr(next_kanji_offset, |
123 | 125 | kanji.size() - next_kanji_offset).toStdString(); |
@@ -125,13 +127,13 @@ | ||
125 | 127 | kana.substr(next_kana_offset, |
126 | 128 | kana.size() - next_kana_offset).toStdString(); |
127 | 129 | return parse(rubi_positions, |
128 | - next_kanji.c_str(), next_kanji_offset, | |
129 | - next_kana.c_str(), next_kana_offset); | |
130 | + next_kanji.c_str(), kanji_offset + next_kanji_offset, | |
131 | + next_kana.c_str(), kana_offset + next_kana_offset); | |
130 | 132 | } |
131 | 133 | } |
132 | 134 | |
133 | 135 | |
134 | -bool qrk::parse_rubi(std::vector<rubi_t>& rubi_positions, | |
136 | +bool qrk::rubi_parse(std::vector<rubi_t>& rubi_positions, | |
135 | 137 | const char* text, const char* kana_only) |
136 | 138 | { |
137 | 139 | return parse(rubi_positions, text, 0, kana_only, 0); |
@@ -22,11 +22,11 @@ | ||
22 | 22 | vector<rubi_t> rubi; |
23 | 23 | |
24 | 24 | rubi.clear(); |
25 | - parse_rubi(rubi, "む", "む"); | |
25 | + rubi_parse(rubi, "む", "む"); | |
26 | 26 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rubi.size()); |
27 | 27 | |
28 | 28 | rubi.clear(); |
29 | - parse_rubi(rubi, "無", "む"); | |
29 | + rubi_parse(rubi, "無", "む"); | |
30 | 30 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi.size()); |
31 | 31 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rubi[0].kanji_first); |
32 | 32 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[0].kanji_size); |
@@ -34,7 +34,7 @@ | ||
34 | 34 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[0].rubi_size); |
35 | 35 | |
36 | 36 | rubi.clear(); |
37 | - parse_rubi(rubi, "無し", "なし"); | |
37 | + rubi_parse(rubi, "無し", "なし"); | |
38 | 38 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi.size()); |
39 | 39 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rubi[0].kanji_first); |
40 | 40 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[0].kanji_size); |
@@ -42,7 +42,7 @@ | ||
42 | 42 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[0].rubi_size); |
43 | 43 | |
44 | 44 | rubi.clear(); |
45 | - parse_rubi(rubi, "よい水", "よいみず"); | |
45 | + rubi_parse(rubi, "よい水", "よいみず"); | |
46 | 46 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi.size()); |
47 | 47 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi[0].kanji_first); |
48 | 48 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[0].kanji_size); |
@@ -50,7 +50,7 @@ | ||
50 | 50 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi[0].rubi_size); |
51 | 51 | |
52 | 52 | rubi.clear(); |
53 | - parse_rubi(rubi, "よい水だ", "よいみずだ"); | |
53 | + rubi_parse(rubi, "よい水だ", "よいみずだ"); | |
54 | 54 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi.size()); |
55 | 55 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi[0].kanji_first); |
56 | 56 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[0].kanji_size); |
@@ -58,7 +58,7 @@ | ||
58 | 58 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi[0].rubi_size); |
59 | 59 | |
60 | 60 | rubi.clear(); |
61 | - parse_rubi(rubi, "秋の田の", "あきのたの"); | |
61 | + rubi_parse(rubi, "秋の田の", "あきのたの"); | |
62 | 62 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi.size()); |
63 | 63 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rubi[0].kanji_first); |
64 | 64 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[0].kanji_size); |
@@ -70,7 +70,7 @@ | ||
70 | 70 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[1].rubi_size); |
71 | 71 | |
72 | 72 | rubi.clear(); |
73 | - parse_rubi(rubi, "あふ坂の関", "あふさかのせき"); | |
73 | + rubi_parse(rubi, "あふ坂の関", "あふさかのせき"); | |
74 | 74 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi.size()); |
75 | 75 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi[0].kanji_first); |
76 | 76 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[0].kanji_size); |
@@ -80,4 +80,23 @@ | ||
80 | 80 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[1].kanji_size); |
81 | 81 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), rubi[1].rubi_first); |
82 | 82 | CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi[1].rubi_size); |
83 | + | |
84 | + rubi.clear(); | |
85 | + rubi_parse(rubi, "今日は卵を食べました。", "きょうはたまごをたべました。"); | |
86 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rubi.size()); | |
87 | + | |
88 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rubi[0].kanji_first); | |
89 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rubi[0].kanji_size); | |
90 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rubi[0].rubi_first); | |
91 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rubi[0].rubi_size); | |
92 | + | |
93 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rubi[1].kanji_first); | |
94 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[1].kanji_size); | |
95 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rubi[1].rubi_first); | |
96 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rubi[1].rubi_size); | |
97 | + | |
98 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), rubi[2].kanji_first); | |
99 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[2].kanji_size); | |
100 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(8), rubi[2].rubi_first); | |
101 | + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rubi[2].rubi_size); | |
83 | 102 | } |
@@ -30,6 +30,7 @@ | ||
30 | 30 | $(INPUT_LIB)(utf8_string.o) \ |
31 | 31 | $(INPUT_LIB)(convertToJp.o) \ |
32 | 32 | $(INPUT_LIB)(convertToRoman.o) \ |
33 | + $(INPUT_LIB)(rubi_parse.o) \ | |
33 | 34 | |
34 | 35 | convertToJp.o : roman_table.h kana_table.h |
35 | 36 | convertToRoman.o : roman_table.h |