Mercurial > otakunoraifu
annotate window/picture.cc @ 66:d112357a0ec1
Fix a bug with savegames introduced with changeset c7bcc0ec2267.
Warning: savegames created since c7bcc0ec2267 are probably corrupted,
you may have to start the game over.
If you chose not to do so, you should replace all occurrences of 'TextWindow' by 'TextImplWindow',
and 'Text Window' by 'TextImpl Window' in your save files.
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Sat, 11 Dec 2010 18:36:20 +0100 |
parents | 4416cfac86ae |
children | 1fd20d231376 |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright (c) 2004-2006 Kazunori "jagarl" Ueno | |
3 * All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
52 | 28 #include <stdio.h> |
29 #include <vector> | |
30 #include <list> | |
31 #include <algorithm> | |
0 | 32 |
52 | 33 #include "rect.h" |
34 #include "event.h" | |
35 #include "font/font.h" | |
36 #include "font/text.h" | |
37 #include <SDL_rotozoom.h> | |
38 #include "system/file.h" | |
0 | 39 |
52 | 40 #include "picture.h" |
0 | 41 |
42 using namespace std; | |
43 | |
44 /* render.cc */ | |
45 void DSurfaceBlitAlpha(Surface* src_o, const Rect& srcrect_o, Surface* dst_o, const Rect& dstrect_o, const unsigned char* alpha, const Rect& alpharect); | |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
46 void DSurfaceBlitAdd(Surface* src_o, const Rect& srcrect, Surface* dst_o, const Rect& dstrect, unsigned char alpha); |
0 | 47 void DSurfaceBlitMultiply(Surface* src_o, const Rect& srcrect, Surface* dst_o, const Rect& dstrect); |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
48 void DSurfaceFill(Surface* src, const Rect& rect, int r, int g, int b, int a=0xff); // クリア |
0 | 49 #if 0 /* DEBUG */ |
50 #include<sys/types.h> | |
51 #include<sys/time.h> | |
52 #define dprintf printf | |
53 static struct timeval tv; | |
54 void gettm(void) { | |
55 gettimeofday(&tv, 0); | |
56 } | |
57 int calctm(void) { | |
58 struct timeval tv2; | |
59 gettimeofday(&tv2, 0); | |
60 int n = (tv2.tv_sec-tv.tv_sec)*100000 + (tv2.tv_usec-tv.tv_usec)/10; | |
61 return n; | |
62 } | |
63 #endif | |
64 | |
65 /****************************************** | |
66 ** PicBase | |
67 */ | |
68 PicBase::PicBase(const Rect& _rel_pos, PicContainer* _parent, int _attr) : | |
69 parent(_parent), rel_pos(_rel_pos), rel_solid_area(0,0,0,0), clip_area(0,0,0,0), | |
70 is_hidden(true), is_hidden_now(true), is_cached(false), attribute(_attr), surface_alpha_rect(0,0) { | |
71 | |
72 if (parent) root = parent->root; | |
52 | 73 else root = NULL; |
74 surface_back = NULL; | |
75 surface_own = NULL; | |
0 | 76 surface_alpha = 0; |
77 surface_x = 0; surface_y = 0; | |
78 surface_w = -1; surface_h = -1; | |
52 | 79 widget = NULL; |
0 | 80 attribute |= NO_PICTURE; |
81 if ( (attribute & CACHE_BACK) && root) { | |
82 surface_back = root->NewSurface(rel_pos.width(), rel_pos.height(), NO_MASK); | |
83 } | |
84 | |
85 if (parent) { | |
86 parent->children.push_back(this); | |
87 z_pos = parent->children.end(); z_pos--; | |
88 distance_root = parent->DistanceRoot() + 1; | |
89 } else { | |
90 distance_root = 1; | |
91 } | |
92 } | |
52 | 93 |
0 | 94 PicBase::~PicBase() { |
95 ClearAnm(); | |
52 | 96 if (widget != NULL) { |
0 | 97 fprintf(stderr,"Warning: PicBase::~PicBase: surface is disallocated but widget is still alive.\n"); |
98 widget->deactivate(); | |
99 } | |
52 | 100 if (surface_back != NULL) root->DeleteSurface(surface_back); |
101 if (surface_own != NULL && (attribute & SURFACE_FREE)) root->DeleteSurface(surface_own); | |
102 if (surface_alpha != NULL && (attribute & ALPHA_FREE)) delete surface_alpha; | |
0 | 103 iterator it; |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
104 if (parent) { // 自分を親から削除 |
0 | 105 parent->children.remove(this); |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
106 // root の update 情報から自分を削除 |
0 | 107 parent->Root().DeleteUpdatePic(this); |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
108 // 自分の領域を書き直す |
0 | 109 Rect old_ppos = rel_pos; |
110 parent->QueryAbsPos(old_ppos); | |
111 parent->ReBlit(old_ppos); | |
112 } | |
113 } | |
52 | 114 |
0 | 115 void PicBase::Blit(const Rect& rpos_orig) { |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
116 // 実際に描画する領域を得る |
0 | 117 Rect rpos = rpos_orig; |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
118 // 親widget上に設定されたclip area 内に描画を限定する |
0 | 119 if (clip_area.width() != 0) { |
120 Rect clip = clip_area; | |
121 clip = child_pos(clip, this); | |
122 rpos.intersect(clip); | |
123 } | |
124 Rect apos = QueryAbsPos(rpos); | |
125 if (rpos.empty()) return; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
126 // 必要に応じて保存、描画 |
0 | 127 if (attribute & CACHE_BACK) root->BlitSurface(root->surface, apos, surface_back, rpos); |
128 if (! (attribute & NO_PICTURE)) { | |
129 rpos.rmove(surface_x, surface_y); | |
130 if (surface_w >= 0 && surface_h >= 0) { | |
131 Rect clip(surface_x, surface_y, surface_x+surface_w, surface_y+surface_h); | |
132 rpos.intersect(clip); | |
133 } | |
48 | 134 //if (apos.ty < 200) fprintf(stderr,"Blit: %p : (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n",surface_own,rpos_orig.lx,rpos_orig.ty,rpos_orig.rx,rpos_orig.by,apos.lx,apos.ty,apos.rx,apos.by); |
0 | 135 root->BlitSurface(surface_own, rpos, surface_alpha, surface_alpha_rect, root->surface, apos, attribute); |
136 rpos.rmove(-surface_x, -surface_y); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
137 } else if (parent == 0) { // 親がいないなら背景消去の責任をもつ |
0 | 138 DSurfaceFill(root->surface, apos, 0, 0, 0); |
139 } | |
140 PicContainer* cur = dynamic_cast<PicContainer*>(this); | |
141 if (cur && (!cur->children.empty())) { | |
142 cur->BlitChildren(rpos); | |
143 } | |
144 } | |
52 | 145 |
0 | 146 void PicBase::SimpleBlit(Surface* screen) { |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
147 // 実際に描画する領域を得る |
0 | 148 Rect rpos(0, 0, rel_pos.width(), rel_pos.height()); |
149 Rect apos = QueryAbsPos(rpos); | |
150 if (rpos.empty()) return; | |
151 rpos.rmove(surface_x, surface_y); | |
152 if (surface_w >= 0 && surface_h >= 0) { | |
153 Rect clip(surface_x, surface_y, surface_x+surface_w, surface_y+surface_h); | |
154 rpos.intersect(clip); | |
155 } | |
48 | 156 //if (apos.ty < 200) fprintf(stderr,"S-Blit: %p : (%d,%d,%d,%d) -> (%d,%d,%d,%d)\n",surface_own,rel_pos.lx,rel_pos.ty,rel_pos.rx,rel_pos.by,apos.lx,apos.ty,apos.rx,apos.by); |
0 | 157 root->BlitSurface(surface_own, rpos, surface_alpha, surface_alpha_rect, screen, apos, attribute); |
158 } | |
159 | |
160 Rect PicBase::QueryAbsPos(Rect& rpos) { | |
161 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); | |
52 | 162 if (parent == NULL) { // root container |
0 | 163 return rpos; |
164 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
165 // 親の座標に変換後、Query する |
0 | 166 Rect ppos = parent_pos(rpos); |
167 Rect apos = parent->QueryAbsPos(ppos); | |
168 rpos = child_pos(ppos, this); | |
169 return apos; | |
52 | 170 } |
171 | |
0 | 172 void PicBase::ReBlit(const Rect& rpos_c) { |
173 Rect rpos = rpos_c; | |
174 Rect apos = QueryAbsPos(rpos); | |
175 root->Update(this, rpos, apos); | |
176 } | |
52 | 177 |
0 | 178 void PicBase::ExecReBlit(const Rect& rpos_c) { |
179 Rect rpos = rpos_c; | |
180 Rect abs_r = QueryAbsPos(rpos); | |
181 Rect ppos = parent_pos(rpos); | |
182 if (parent) parent->BlitBack(z_pos, ppos); | |
183 if (!is_hidden_now) Blit(rpos); | |
184 if (parent) parent->BlitFront(z_pos, ppos); | |
185 } | |
186 | |
187 void PicBase::ZMove(PicBase* move_to) { | |
52 | 188 if (parent == NULL) { |
0 | 189 fprintf(stderr,"Warning: PicBase::ZMove is called by root.\n"); |
190 return; | |
191 } | |
192 if (move_to == ZMOVE_TOP) { | |
193 if (this == parent->children.back()) return; | |
194 } else if (move_to == ZMOVE_BOTTOM) { | |
195 if (this == parent->children.front()) return; | |
196 } else if (move_to == this) { | |
197 fprintf(stderr,"Error: PicBase::ZMove : move in front of itself!\n"); | |
198 return; | |
199 } else if (move_to && move_to->parent != parent) { | |
200 fprintf(stderr,"Error: PicBase::ZMove was called with a no-brother picture\n"); | |
201 return; | |
202 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
203 // move_to と zpos のうち、後ろの方の picture から書きなおす必要がある |
0 | 204 iterator redraw_zpos = z_pos; redraw_zpos++; |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
205 if (move_to == ZMOVE_BOTTOM) { // 最背面へ |
0 | 206 parent->children.erase(z_pos); |
207 parent->children.push_front(this); | |
208 z_pos = parent->children.begin(); | |
209 redraw_zpos = parent->children.begin(); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
210 } else if (move_to == ZMOVE_TOP) { // 最前面へ |
0 | 211 redraw_zpos = z_pos; redraw_zpos++; |
212 parent->children.erase(z_pos); | |
213 parent->children.push_back(this); | |
214 z_pos = parent->children.end(); z_pos--; | |
215 } else { | |
216 int dis_to = distance(move_to->parent->children.begin(), move_to->z_pos); | |
217 int dis_cur = distance(parent->children.begin(), z_pos); | |
218 if (dis_cur < dis_to) redraw_zpos = move_to->z_pos; | |
219 parent->children.erase(z_pos); | |
220 iterator insert_pos = move_to->z_pos; insert_pos++; | |
221 parent->children.insert(insert_pos, this); | |
222 z_pos = move_to->z_pos; z_pos++; | |
223 } | |
224 if (! is_hidden_now) { | |
225 is_cached = false; | |
226 ReBlit(); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
227 /* @@@ parent->Blit() と Blit() の違いが分からないので修正 06/12/02 |
0 | 228 Rect ppos = rel_pos; |
229 parent->QueryAbsPos(ppos); | |
230 parent->ReBlit(ppos); | |
231 */ | |
232 } | |
52 | 233 } |
234 | |
0 | 235 void PicBase::RMove(int add_x, int add_y) { |
236 Rect old_ppos = rel_pos; | |
237 rel_pos.rmove(add_x, add_y); | |
238 parent->QueryAbsPos(old_ppos); | |
239 parent->ReBlit(old_ppos); | |
240 ReBlit(); | |
241 | |
52 | 242 if (widget != NULL) { |
0 | 243 Rect new_ppos = rel_pos; |
244 Rect new_apos = parent->QueryAbsPos(new_ppos); | |
245 widget->SetRegion(new_apos); | |
246 } | |
247 } | |
52 | 248 |
0 | 249 void PicBase::Move(int new_rx, int new_ry) { |
250 RMove(new_rx-rel_pos.lx, new_ry-rel_pos.ty); | |
251 } | |
52 | 252 |
0 | 253 void PicBase::SetEventWidget(PicWidget* new_widget) { |
254 widget = new_widget; | |
52 | 255 if (widget != NULL) { |
0 | 256 Rect new_ppos = rel_pos; |
257 Rect apos = parent->QueryAbsPos(new_ppos); | |
258 widget->SetRegion(apos); | |
259 } | |
260 } | |
52 | 261 |
0 | 262 void PicBase::show_all(void) { |
263 PicContainer* cont = dynamic_cast<PicContainer*>(this); | |
264 if (cont && (!cont->children.empty())) cont->set_showflag(); | |
265 show(); | |
266 } | |
52 | 267 |
0 | 268 bool PicBase::IsParent(PicBase* to) { |
269 if (parent == 0) return false; | |
270 if (parent == to) return true; | |
271 return parent->IsParent(to); | |
272 } | |
52 | 273 |
0 | 274 void PicBase::show(void) { |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
275 /* 自分の親がすべて shown か? */ |
0 | 276 PicContainer* cur; |
277 for (cur = parent; cur != 0; cur = cur->parent) | |
278 if (cur->is_hidden) break; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
279 if (cur != NULL) { // 親が隠れているので表示はしない |
0 | 280 is_hidden = false; |
281 is_hidden_now = true; | |
282 return; | |
283 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
284 if (is_hidden == false) return; // すでに表示されているのでなにもしない |
52 | 285 if (widget != NULL) { |
0 | 286 widget->activate(); |
287 } | |
288 is_hidden = false; | |
289 is_hidden_now = false; | |
290 is_cached = false; | |
291 cur = dynamic_cast<PicContainer*>(this); | |
292 if (cur && (!cur->children.empty())) cur->set_nowhiddenflag(false); | |
293 ReBlit(); | |
294 } | |
52 | 295 |
0 | 296 void PicBase::hide(void) { |
297 if (is_hidden) return; | |
52 | 298 if (widget != NULL) { |
0 | 299 widget->deactivate(); |
300 } | |
301 is_hidden = true; | |
302 is_hidden_now = true; | |
303 is_cached = false; | |
304 PicContainer* cur = dynamic_cast<PicContainer*>(this); | |
305 if (cur && (!cur->children.empty())) cur->set_nowhiddenflag(true); | |
306 ReBlit(); | |
307 } | |
52 | 308 |
0 | 309 void PicBase::SetSurfaceAlpha(const unsigned char* alpha, const Rect& alpha_r) { |
310 if (attribute & ALPHA_FREE) { | |
311 if (surface_alpha) delete[] surface_alpha; | |
312 surface_alpha = 0; | |
313 } | |
314 surface_alpha = alpha; | |
315 surface_alpha_rect = alpha_r; | |
316 if (!is_hidden) ReBlit(); | |
317 } | |
52 | 318 |
0 | 319 void PicBase::SetSurfaceColorKey(int r, int g, int b) { |
320 surface_alpha = 0; | |
321 surface_alpha_rect = Rect(0,0); | |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
322 attribute &= ~(BLIT_ADD | BLIT_MULTIPLY); |
0 | 323 if (surface_own) { |
324 int key = SDL_MapRGB( ((SDL_Surface*)surface_own)->format, r, g, b); | |
325 key |= 0xff000000; | |
326 SDL_SetColorKey( (SDL_Surface*)surface_own, SDL_SRCCOLORKEY, key); | |
327 } | |
328 if (!is_hidden) ReBlit(); | |
329 } | |
52 | 330 |
0 | 331 void PicBase::SetSurfaceAlphaFile(const char* file) { |
332 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
333 /* ファイルを元に alpha 画像を作成する */ |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
334 /* ファイル: パルフェの 'fil' ファイル */ |
53
ddbcbd000206
* MuSys, AyuSysConfig, FileSearcher (former FILESEARCHER) and KeyHolder (former KEYHOLDER) are now singletons
thib
parents:
52
diff
changeset
|
335 ARCINFO* info = FileSearcher::GetInstance()->Find(FileSearcher::PDT, file,"fil"); |
52 | 336 if (info == NULL) return; |
0 | 337 char* new_alpha = info->CopyRead(); |
338 int alpha_size = info->Size(); | |
339 delete info; | |
340 Rect sr(0,0); int w,h; | |
52 | 341 if (surface_own == NULL || new_alpha == NULL) { |
0 | 342 err_ret: |
343 if (new_alpha) delete[] new_alpha; | |
344 SetSurfaceAlpha(0,Rect(0,0)); | |
345 return; | |
346 } | |
347 sr = Rect(*surface_own); | |
348 w = sr.width(); | |
349 h = sr.height(); | |
350 if (alpha_size < w*h) goto err_ret; | |
351 int i,j; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
352 if ( ((SDL_Surface*)surface_own)->format->Amask == 0) { // mask を surface に繰り込む |
0 | 353 Surface* dest = root->NewSurface(w,h, ALPHA_MASK); |
354 for (i=0; i<h; i++) { | |
355 char* a = new_alpha + w*i; | |
356 char* s = (char*)((SDL_Surface*)surface_own)->pixels + ((SDL_Surface*)surface_own)->pitch*i; | |
357 char* d = (char*)((SDL_Surface*)dest)->pixels + ((SDL_Surface*)dest)->pitch*i; | |
358 int sbpp = ((SDL_Surface*)surface_own)->format->BytesPerPixel; | |
359 int dbpp = ((SDL_Surface*)dest)->format->BytesPerPixel; | |
360 | |
361 for (j=0; j<w; j++) { | |
362 int d = read_little_endian_int(s); | |
363 d &= 0xffffff; | |
364 if (d == 0) ; | |
365 else if (*a == 0) d |= 0xff000000; | |
366 else d |= (int(*a) << 24); | |
367 s += sbpp; d += dbpp; a++; | |
368 } | |
369 } | |
370 delete new_alpha; | |
371 root->DeleteSurface(surface_own); | |
372 surface_own = dest; | |
373 SetSurfaceAlpha(0, Rect(0,0)); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
374 } else { // 外部にマスク作成 |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
375 /* マスクのうち、0xff であるべき部分を画像から判別、変更する */ |
0 | 376 for (i=0; i<h; i++) { |
377 char* a = new_alpha + w*i; | |
378 char* s = (char*)((SDL_Surface*)surface_own)->pixels + ((SDL_Surface*)surface_own)->pitch*i; | |
379 int bpp = ((SDL_Surface*)surface_own)->format->BytesPerPixel; | |
380 for (j=0; j<w; j++) { | |
381 if ( ((*(int*)s) & 0xffffff) == 0) *a = 0; | |
382 else if (*a == 0) *a = 0xff; | |
383 s += bpp; a++; | |
384 } | |
385 } | |
386 SetSurfaceAlpha( (unsigned char*)new_alpha, Rect(0,0,w,h)); | |
387 attribute |= ALPHA_FREE; | |
388 } | |
389 } | |
52 | 390 |
0 | 391 void PicBase::SetSurface(const char* filename, int x, int y) { |
392 Surface* s = root->NewSurface(filename); | |
393 SetSurface(s, x, y, SURFACE_FREE); | |
394 } | |
52 | 395 |
0 | 396 void PicBase::SetSurface(Surface* new_surface, int x, int y, int new_attr) { |
52 | 397 if (surface_own != NULL && (attribute & SURFACE_FREE)) { |
0 | 398 root->DeleteSurface(surface_own); |
399 } | |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
400 attribute &= ~(SURFACE_FREE | BLIT_ADD | BLIT_MULTIPLY | NO_PICTURE | SOLID); |
0 | 401 attribute |= new_attr; |
402 surface_own = new_surface; | |
403 surface_x = x; | |
404 surface_y = y; | |
405 surface_w = -1; | |
406 surface_h = -1; | |
407 | |
408 if (attribute & FIT_SURFACE) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
409 // surface の大きさに自分の大きさを変更 |
0 | 410 parent->ReBlit(rel_pos); |
411 if (surface_own == 0) { | |
412 rel_pos = Rect(rel_pos.lx, rel_pos.ty); | |
413 } else { | |
414 Rect r(*surface_own); | |
415 int w = r.width(), h = r.height(); | |
416 w -= x; h -= y; | |
417 rel_pos = Rect(rel_pos.lx, rel_pos.ty, rel_pos.lx+w, rel_pos.ty+h); | |
418 } | |
419 } | |
420 | |
421 rel_solid_area = Rect(0,0,0,0); | |
52 | 422 if (surface_own == NULL) attribute |= NO_PICTURE; |
0 | 423 else if (root->with_mask(surface_own) == 0) { |
424 attribute |= SOLID; | |
425 rel_solid_area = rel_pos; | |
426 } | |
427 if (!is_hidden) ReBlit(); | |
428 } | |
52 | 429 |
0 | 430 void PicBase::SetSurfacePos(int x, int y) { |
431 if (surface_x == x && surface_y == y && surface_w == -1 && surface_h == -1) return; | |
432 surface_x = x; surface_y = y; | |
433 surface_w = -1; surface_h = -1; | |
434 if (!is_hidden_now) ReBlit(); | |
435 } | |
52 | 436 |
0 | 437 int PicBase::SurfacePosX(void) { |
438 return surface_x; | |
439 } | |
52 | 440 |
0 | 441 int PicBase::SurfacePosY(void) { |
442 return surface_y; | |
443 } | |
52 | 444 |
0 | 445 void PicBase::SetSurfaceRect(const Rect& r) { |
446 if (surface_x == r.lx && surface_y == r.ty && surface_w == r.width() && surface_h == r.height()) return; | |
52 | 447 surface_x = r.lx; |
448 surface_y = r.ty; | |
0 | 449 surface_w = r.width(); surface_h = r.height(); |
450 parent->ReBlit(rel_pos); | |
451 rel_pos = Rect(rel_pos.lx, rel_pos.ty, rel_pos.lx+surface_w, rel_pos.ty+surface_h); | |
52 | 452 if (widget != NULL) { |
0 | 453 Rect new_ppos = rel_pos; |
454 Rect apos = parent->QueryAbsPos(new_ppos); | |
455 widget->SetRegion(apos); | |
456 } | |
457 if (!is_hidden_now) ReBlit(); | |
458 } | |
52 | 459 |
0 | 460 void PicBase::SetClipArea(const Rect& r) { |
461 if (clip_area == r) return; | |
462 clip_area = r; | |
463 parent->ReBlit(rel_pos); | |
464 } | |
465 | |
466 void PicBase::SetSurfaceAttribute(int new_attribute) { | |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
467 attribute &= ~(BLIT_ADD | BLIT_MULTIPLY); |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
468 attribute |= new_attribute & (BLIT_ADD | BLIT_MULTIPLY); |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
469 if (new_attribute & (BLIT_ADD | BLIT_MULTIPLY)) { |
0 | 470 rel_solid_area = Rect(0,0); |
471 } | |
472 } | |
52 | 473 |
0 | 474 void PicBase::SetSurfaceFreeFlag(bool flag) { |
475 if (flag) attribute |= SURFACE_FREE; | |
476 else attribute &= ~SURFACE_FREE; | |
477 | |
478 } | |
479 | |
480 /****************************************** | |
481 ** PicContainer | |
482 */ | |
483 PicContainer::PicContainer(const Rect& rel_pos, PicContainer* parent, int attr) : | |
484 PicBase(rel_pos, parent, attr) { | |
485 } | |
52 | 486 |
0 | 487 PicContainer::~PicContainer() { |
488 iterator end = children.end(); | |
489 for (iterator it = children.begin(); it != end; ) { | |
490 iterator it_next = it; it_next++; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
491 if ((*it)->widget != NULL) delete (*it)->widget; // picture にwidget が付属しているなら、そちらをdelete |
0 | 492 else delete (*it); |
493 it = it_next; | |
494 } | |
495 } | |
52 | 496 |
0 | 497 void PicContainer::BlitBack(iterator z, Rect rpos) { |
498 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); | |
499 if (rpos.empty()) return; | |
52 | 500 iterator end = children.end(), begin = children.begin(); |
501 iterator it = begin; | |
0 | 502 |
503 Rect ppos = parent_pos(rpos); | |
504 if (is_hidden_now) goto parent_redraw; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
505 // cache されている領域を探す |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
506 // z自身がキャッシュしていれば、ここで終了 |
0 | 507 if ( ((*z)->attribute & CACHE_BACK) && ( (*z)->is_cached) && (*z)->rel_pos.is_inner(rpos)) { |
508 Rect cpos = child_pos(rpos, *z); | |
509 Rect apos = (*z)->QueryAbsPos(cpos); | |
510 root->BlitSurface( (*z)->surface_back, cpos, root->surface, apos); | |
511 return; | |
512 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
513 // z より下の子がキャッシュ、あるいは SOLID 描画できないか? |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
514 for (it = z; it != begin;) { // 子がcontainerの場合のチェックは省略 |
0 | 515 it--; |
516 if ( (*it)->is_hidden_now) continue; | |
517 if ( (*it)->rel_pos.is_crossed(rpos)) { | |
518 if ( ((*it)->attribute & CACHE_BACK) && ((*it)->is_cached) && (*it)->rel_pos.is_inner(rpos)) { | |
519 Rect cpos = child_pos(rpos, *it); | |
520 Rect apos = (*it)->QueryAbsPos(cpos); | |
521 root->BlitSurface( (*it)->surface_back, cpos, root->surface, apos); | |
522 goto children_redraw; | |
523 } | |
524 if ( (*it)->rel_solid_area.is_inner(rpos)) { | |
525 goto children_redraw; | |
526 } | |
527 } | |
528 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
529 // 自分自身がキャッシュ、あるいは SOLID 描画できないか? |
0 | 530 if (rel_solid_area.is_inner(ppos)) { |
531 goto self_redraw; | |
532 } | |
533 if ( (attribute & CACHE_BACK) && is_cached) { | |
534 Rect cpos = child_pos(rpos, *z); | |
535 Rect apos = (*z)->QueryAbsPos(cpos); | |
536 Rect draw_rpos = (*z)->parent_pos(cpos); | |
537 root->BlitSurface(surface_back, draw_rpos, root->surface, apos); | |
538 goto self_redraw; | |
539 } | |
540 parent_redraw: | |
541 if (parent) { | |
542 Rect ppos = parent_pos(rpos); | |
543 parent->BlitBack(z_pos, ppos); | |
544 } | |
545 if (is_hidden_now) return; | |
546 self_redraw: | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
547 BlitSelf(rpos); // 子は描画せず、自分だけ描画 |
0 | 548 children_redraw: |
549 for (; it != z; it++) { | |
550 if ( (*it)->is_hidden_now) continue; | |
551 if ( (*it)->rel_pos.is_crossed(rpos)) { | |
552 Rect cpos = child_pos(rpos, *it); | |
553 (*it)->Blit(cpos); | |
554 } | |
555 } | |
556 } | |
52 | 557 |
0 | 558 void PicContainer::BlitChildren(Rect rpos) { |
559 iterator end = children.end(); | |
560 for (iterator it = children.begin(); it != end; it++) { | |
561 if ( (*it)->is_hidden_now) continue; | |
562 if ( (*it)->rel_pos.is_crossed(rpos)) { | |
563 Rect cpos = child_pos(rpos, *it); | |
564 (*it)->Blit(cpos); | |
565 } | |
566 } | |
567 } | |
52 | 568 |
0 | 569 void PicContainer::BlitFront(iterator z, Rect rpos) { |
570 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); | |
571 if (rpos.empty()) return; | |
52 | 572 iterator end = children.end(); |
573 iterator it; | |
0 | 574 z++; |
575 for (it = z; it != end; it++) { | |
576 if ( (*it)->is_hidden_now) continue; | |
577 if ( (*it)->rel_pos.is_crossed(rpos)) { | |
578 Rect cpos = child_pos(rpos, *it); | |
579 (*it)->Blit(cpos); | |
580 } | |
581 } | |
582 if (parent) { | |
583 Rect ppos = parent_pos(rpos); | |
584 parent->BlitFront(z_pos, ppos); | |
585 } | |
52 | 586 } |
587 | |
0 | 588 void PicContainer::BlitSelf(Rect rpos) { |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
589 // 実際に描画する領域を得る |
0 | 590 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); |
591 if (rpos.empty()) return; | |
592 Rect apos = QueryAbsPos(rpos); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
593 // 必要に応じて保存、描画 |
0 | 594 if (attribute & CACHE_BACK) root->BlitSurface(root->surface, apos, surface_back, rpos); |
595 if (! (attribute & NO_PICTURE)) { | |
596 rpos.rmove(surface_x, surface_y); | |
597 if (surface_w >= 0 && surface_h >= 0) { | |
598 Rect clip(0, 0, surface_w, surface_h); | |
599 clip.rmove(rpos.lx, rpos.ty); | |
600 rpos.intersect(clip); | |
601 } | |
602 root->BlitSurface(surface_own, rpos, surface_alpha, surface_alpha_rect, root->surface, apos, attribute); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
603 } else if (parent == NULL) { // 親がいないなら背景消去の責任をもつ |
0 | 604 DSurfaceFill(root->surface, apos, 0, 0, 0); |
605 } | |
606 } | |
607 | |
608 void PicContainer::set_showflag(void) { | |
609 iterator end = children.end(); | |
610 for (iterator it = children.begin(); it != end; it++) { | |
611 (*it)->is_hidden = false; | |
612 PicContainer* next = dynamic_cast<PicContainer*>(*it); | |
613 if (next && (!next->children.empty())) next->set_showflag(); | |
614 } | |
615 } | |
52 | 616 |
0 | 617 void PicContainer::set_nowhiddenflag(bool is_hide) { |
618 iterator end = children.end(); | |
619 for (iterator it = children.begin(); it != end; it++) { | |
620 if (is_hide) (*it)->is_hidden_now = true; | |
621 else (*it)->is_hidden_now = (*it)->is_hidden; | |
52 | 622 if ( (*it)->widget != NULL) { |
0 | 623 if ((*it)->is_hidden_now) (*it)->widget->deactivate(); |
624 else (*it)->widget->activate(); | |
625 } | |
626 PicContainer* next = dynamic_cast<PicContainer*>(*it); | |
627 if (next && (!next->children.empty())) next->set_nowhiddenflag(is_hide); | |
628 } | |
629 } | |
52 | 630 |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
631 void PicContainer::RMove(int add_x, int add_y) { // event widget の移動があり得るので子についてもRMoveを呼び出す |
0 | 632 PicBase::RMove(add_x, add_y); |
633 iterator end = children.end(); | |
634 for (iterator it = children.begin(); it != end; it++) { | |
635 (*it)->RMove(0,0); | |
636 } | |
637 } | |
638 | |
639 PicBase* PicContainer::create_leaf(const Rect& rel_pos, int attr) { | |
640 return new PicBase(rel_pos, this, attr); | |
641 } | |
52 | 642 |
0 | 643 PicContainer* PicContainer::create_node(const Rect& rel_pos, int attr) { |
644 return new PicContainer(rel_pos, this, attr); | |
645 } | |
646 | |
647 /*************************************************************** | |
648 ** | |
649 ** PicWidget | |
650 */ | |
651 | |
652 PicWidget::PicWidget(void) { | |
52 | 653 pic = NULL; |
0 | 654 } |
52 | 655 |
0 | 656 PicWidget::~PicWidget() { |
52 | 657 if (pic != NULL) { |
0 | 658 pic->SetEventWidget(0); |
659 delete pic; | |
660 } | |
52 | 661 pic = NULL; |
0 | 662 } |
52 | 663 |
0 | 664 void PicWidget::SetPic(PicBase* new_pic) { |
52 | 665 if (pic != NULL) { |
0 | 666 pic->SetEventWidget(0); |
667 delete pic; | |
668 } | |
669 pic = new_pic; | |
52 | 670 if (pic != NULL) pic->SetEventWidget(this); |
0 | 671 } |
52 | 672 |
0 | 673 PicBase* PicWidget::Pic(void) { |
52 | 674 if (pic == NULL) { |
0 | 675 fprintf(stderr,"Error: PicWidget::Pic returns zero.\n"); |
676 } | |
677 return pic; | |
678 } | |
52 | 679 |
0 | 680 PicContainer* PicWidget::PicNode(void) { |
681 PicContainer* node = dynamic_cast<PicContainer*>(pic); | |
52 | 682 if (node == NULL) { |
0 | 683 fprintf(stderr,"Error: PicWidget::PicNode returns zero.\n"); |
684 } | |
685 return node; | |
686 } | |
687 | |
688 /****************************************** | |
689 ** FileToSurface | |
690 */ | |
691 | |
52 | 692 #include <list> |
693 #include <map> | |
694 #include <string> | |
695 | |
0 | 696 using namespace std; |
697 struct SurfaceIndex { | |
698 typedef list<SurfaceIndex*>::iterator qiterator; | |
699 string filename; | |
700 Surface* surface; | |
701 qiterator qpos; | |
702 int ref_count; | |
703 }; | |
704 | |
705 class FileToSurface { | |
52 | 706 private: |
707 typedef list<SurfaceIndex*>::iterator qiterator; | |
0 | 708 |
52 | 709 list<SurfaceIndex*> queue; |
710 map<string, SurfaceIndex*> findex; | |
711 map<Surface*, SurfaceIndex*> mindex; | |
712 int count; | |
713 int count_max; | |
714 const PicRoot& root; | |
715 bool DeleteData(SurfaceIndex* data); | |
716 Surface* LoadSurface(string name, char*& mem); | |
717 | |
718 public: | |
719 FileToSurface(const PicRoot& root); | |
720 ~FileToSurface(void); | |
721 Surface* Load(string name); | |
722 bool Free(Surface* s); | |
0 | 723 }; |
724 | |
725 FileToSurface::FileToSurface(const PicRoot& _root) : root(_root) { | |
726 count = 0; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
727 count_max = 32; // キャッシュ量(決め打ち) |
0 | 728 }; |
52 | 729 |
0 | 730 FileToSurface::~FileToSurface() { |
731 qiterator it; | |
732 for (it=queue.begin(); it != queue.end(); it++) { | |
733 if ( (*it)->ref_count) { | |
734 fprintf(stderr, "Warning: FileToSurface: delete referenced surface named '%s'\n",(*it)->filename.c_str()); | |
735 } | |
736 root.DeleteSurfaceImpl( (*it)->surface); | |
737 delete *it; | |
738 } | |
739 } | |
52 | 740 |
0 | 741 inline bool FileToSurface::DeleteData(SurfaceIndex* data) { |
742 if ( data->ref_count) return false; | |
743 findex.erase(data->filename); | |
744 mindex.erase(data->surface); | |
745 queue.erase(data->qpos); | |
746 root.DeleteSurfaceImpl(data->surface); | |
747 delete data; | |
748 count--; | |
749 return true; | |
750 } | |
52 | 751 |
0 | 752 inline Surface* FileToSurface::LoadSurface(string name, char*& mem) { |
53
ddbcbd000206
* MuSys, AyuSysConfig, FileSearcher (former FILESEARCHER) and KeyHolder (former KEYHOLDER) are now singletons
thib
parents:
52
diff
changeset
|
753 ARCINFO* info = FileSearcher::GetInstance()->Find(FileSearcher::PDT, name.c_str(), "pdt"); |
52 | 754 if (info == NULL) return NULL; |
0 | 755 GRPCONV* conv = GRPCONV::AssignConverter(info); |
52 | 756 if (conv == NULL) { |
757 delete info; | |
758 return NULL; | |
759 } | |
0 | 760 mem = (char*)malloc(conv->Width() * conv->Height() * 4 + 1024); |
52 | 761 Surface* s = NULL; |
0 | 762 if (conv->Read(mem)) { |
763 MaskType is_mask = conv->IsMask() ? ALPHA_MASK : NO_MASK; | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
764 if (is_mask == ALPHA_MASK) { // alpha がすべて 0xff ならマスク無しとする |
0 | 765 int len = conv->Width()*conv->Height(); |
766 unsigned int* d = (unsigned int*)mem; | |
767 int i; for (i=0; i<len; i++) { | |
768 if ( (*d&0xff000000) != 0xff000000) break; | |
769 d++; | |
770 } | |
771 if (i == len) { | |
772 is_mask = NO_MASK; | |
773 } | |
774 } | |
775 s = root.NewSurfaceFromRGBAData(conv->Width(), conv->Height(), mem, is_mask); | |
776 } | |
777 delete conv; delete info; // delete data; | |
778 return s; | |
779 } | |
52 | 780 |
0 | 781 Surface* FileToSurface::Load(string name) { |
782 if (findex.find(name) != findex.end()) { | |
783 findex[name]->ref_count++; | |
784 return findex[name]->surface; | |
785 } | |
786 char* mem; | |
787 Surface* surface = LoadSurface(name, mem); | |
52 | 788 if (surface == NULL) return NULL; |
0 | 789 |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
790 while (count >= count_max) { // count_max 以上のデータを可能なら削除する |
0 | 791 qiterator it; |
792 for (it=queue.begin(); it != queue.end(); it++) { | |
793 if (DeleteData(*it)) break; | |
794 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
795 if (it == queue.end()) break; // 全データが使用中なら終了 |
0 | 796 } |
797 SurfaceIndex* new_index = new SurfaceIndex; | |
798 new_index->filename = name; | |
799 new_index->surface = surface; | |
800 findex[name] = new_index; | |
801 mindex[surface] = new_index; | |
802 queue.push_back(new_index); | |
803 new_index->qpos = queue.end(); new_index->qpos--; | |
804 new_index->ref_count = 1; | |
805 count++; | |
806 return surface; | |
807 } | |
52 | 808 |
0 | 809 bool FileToSurface::Free(Surface* s) { |
810 if (mindex.find(s) == mindex.end()) { | |
811 return false; | |
812 } | |
813 SurfaceIndex* index = mindex[s]; | |
814 if (index->ref_count == 0) DeleteData(index); | |
815 else index->ref_count--; | |
816 return true; | |
817 } | |
818 | |
819 /****************************************** | |
820 ** PicRoot | |
821 */ | |
52 | 822 #include <SDL.h> |
0 | 823 |
52 | 824 #include "surface.h" |
0 | 825 |
826 #define DefaultRmask 0xff0000 | |
827 #define DefaultGmask 0xff00 | |
828 #define DefaultBmask 0xff | |
829 #define DefaultAmask 0xff000000 | |
830 #define DefaultBpp 32 | |
831 | |
832 PicRoot::PicRoot(void) { | |
833 hw_surface = (Surface*)SDL_GetVideoSurface(); | |
834 SDL_PixelFormat* fmt_SDL = hw_surface->format; | |
835 if (fmt_SDL->BitsPerPixel == DefaultBpp && fmt_SDL->Rmask == DefaultRmask && fmt_SDL->Gmask == DefaultGmask && fmt_SDL->Bmask == DefaultBmask) { | |
836 surface = hw_surface; | |
837 } else { | |
838 surface = (Surface*)SDL_CreateRGBSurface(0, hw_surface->w, hw_surface->h, DefaultBpp, DefaultRmask, DefaultGmask, DefaultBmask, 0); | |
839 } | |
840 | |
841 Rect rpos(0, 0, surface->w, surface->h); | |
842 root = new PicContainer(rpos, 0, 0); | |
843 root->InitRoot(this); | |
844 root->show(); | |
845 ftosurface = new FileToSurface(*this); | |
846 width = surface->w; | |
847 height = surface->h; | |
848 return; | |
849 } | |
52 | 850 |
0 | 851 PicRoot::~PicRoot() { |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
852 // if (surface) DeleteSurfaceImpl(surface); // SDL_GetVideoSurface() した surface は開放の必要がないらしい |
52 | 853 surface = NULL; |
0 | 854 delete root; |
855 delete ftosurface; | |
856 } | |
52 | 857 |
0 | 858 void PicRoot::Update(PicBase* pic, const Rect& rpos, const Rect& apos) { |
859 update_rects.push_back(UpdateItem(pic, rpos, apos)); | |
860 } | |
52 | 861 |
0 | 862 bool PicRoot::UpdateItem::less(const PicRoot::UpdateItem& a, const PicRoot::UpdateItem& b) { |
863 return a.pic->DistanceRoot() < b.pic->DistanceRoot(); | |
864 } | |
52 | 865 |
0 | 866 void PicRoot::DeleteUpdatePic(PicBase* pic) { |
867 vector<UpdateItem>::iterator it = update_rects.begin(); | |
868 while(it != update_rects.end()) { | |
869 if (it->pic == pic) { | |
870 update_rects.erase(it); | |
871 it = update_rects.begin(); | |
872 continue; | |
873 } | |
874 it++; | |
875 } | |
876 return; | |
877 } | |
52 | 878 |
0 | 879 void PicRoot::ExecUpdate(void) { |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
880 /* 共通する領域を消去する */ |
0 | 881 sort(update_rects.begin(), update_rects.end(), UpdateItem::less); |
882 vector<UpdateItem>::iterator it; | |
883 vector<UpdateItem>::iterator end = update_rects.end(); | |
52 | 884 |
0 | 885 for (it=update_rects.begin(); it != end; it++) { |
886 if (it->rpos.width() == 0) continue; | |
887 | |
888 Rect apos = it->apos; | |
889 PicBase* pic = it->pic; | |
890 | |
891 vector<UpdateItem>::iterator jt = it; jt++; | |
892 for (; jt != end; jt++) { | |
893 if (apos.is_inner(jt->apos)) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
894 if (jt->pic == pic || jt->pic->IsParent(pic)) { // 親が共通、かつ領域も共通 |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
895 jt->rpos = Rect(0,0); // empty rect をセット |
0 | 896 jt->apos = Rect(0,0); |
897 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
898 } else if (jt->apos.is_inner(apos)) { // 相手に自分が包含される |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
899 if (jt->pic == pic || jt->pic->IsParent(pic)) { // 親が共通、かつ領域も共通 |
0 | 900 it->rpos = Rect(0,0); |
901 it->apos = Rect(0,0); | |
902 break; | |
903 } | |
904 } | |
905 } | |
906 } | |
52 | 907 |
0 | 908 int num = update_rects.size(); |
909 SDL_Rect* r = new SDL_Rect[num]; | |
910 Rect confine = Rect(0, 0, surface->w, surface->h); | |
911 int n = 0; | |
912 int i; | |
913 for (i=0; i<num; i++) { | |
914 UpdateItem& item = update_rects[i]; | |
915 Rect& ur = item.apos; | |
916 if (ur.width() == 0) continue; | |
917 | |
918 item.pic->ExecReBlit(item.rpos); | |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
919 |
0 | 920 ur.intersect(confine); |
921 r[n].x = ur.lx; | |
922 r[n].y = ur.ty; | |
923 r[n].w = ur.rx - ur.lx; | |
924 r[n].h = ur.by - ur.ty; | |
925 if (surface != hw_surface) SDL_BlitSurface(surface, &r[n], hw_surface, &r[n]); | |
926 n++; | |
927 } | |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
928 |
0 | 929 SDL_UpdateRects(hw_surface, n, r); |
52 | 930 delete[] r; |
931 update_rects.clear(); | |
0 | 932 } |
933 | |
934 Surface* PicRoot::NewSurface(int w, int h, MaskType with_mask) const { | |
935 Surface* s; | |
936 if (with_mask == ALPHA_MASK) { | |
937 s = (Surface*)SDL_CreateRGBSurface(SDL_SRCALPHA, w, h, DefaultBpp, DefaultRmask, DefaultGmask, DefaultBmask, DefaultAmask); | |
938 } else { | |
939 s = (Surface*)SDL_CreateRGBSurface(0, w, h, DefaultBpp, DefaultRmask, DefaultGmask, DefaultBmask, 0); | |
940 } | |
941 return s; | |
942 } | |
943 | |
944 Surface* PicRoot::NewSurfaceFromRGBAData(int w, int h, char* data, MaskType with_mask) const { | |
945 int amask = (with_mask == ALPHA_MASK) ? DefaultAmask : 0; | |
946 Surface* s = (Surface*)SDL_CreateRGBSurfaceFrom(data, w, h, DefaultBpp, w*4, DefaultRmask, DefaultGmask, DefaultBmask, amask); | |
947 s->flags &= ~SDL_PREALLOC; | |
948 return s; | |
52 | 949 } |
950 | |
0 | 951 Surface* PicRoot::NewSurface(const char* f, MaskType with_mask) { |
52 | 952 if (f == NULL) return NULL; |
0 | 953 Surface* s = ftosurface->Load(f); |
52 | 954 if (s == NULL) return NULL; |
0 | 955 if (with_mask == COLOR_MASK) { |
956 SDL_SetColorKey( (SDL_Surface*)s, SDL_SRCCOLORKEY, *(Uint32*)s->pixels); | |
957 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
958 /* xkanon の残骸 */ |
0 | 959 if (strcmp(f, "grdat") == 0) |
960 SDL_SetColorKey(s, SDL_SRCCOLORKEY, 0x55aa66); | |
961 return s; | |
962 } | |
52 | 963 |
0 | 964 Surface* PicRoot::RotZoomSurface(Surface* from, double zoom, double rotate) { |
965 Surface* ret = (Surface*)rotozoomSurface( (SDL_Surface*)from, rotate, zoom, SMOOTHING_OFF); | |
966 return ret; | |
967 } | |
52 | 968 |
0 | 969 void PicRoot::DeleteSurfaceImpl(Surface* s) const { |
970 SDL_FreeSurface(s); | |
971 } | |
52 | 972 |
0 | 973 void PicRoot::DeleteSurface(Surface* s) { |
974 if (!ftosurface->Free(s)) | |
975 DeleteSurfaceImpl(s); | |
976 } | |
52 | 977 |
0 | 978 inline SDL_Rect SDLed(const Rect& rect) { |
979 SDL_Rect r; | |
980 r.x = rect.lx; | |
981 r.y = rect.ty; | |
982 r.w = rect.rx-rect.lx; | |
983 r.h = rect.by-rect.ty; | |
984 return r; | |
985 } | |
986 | |
987 #ifndef ALPHA_MAX | |
988 #define ALPHA_MAX 255 | |
989 #endif | |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
990 void PicRoot::BlitSurface(Surface* src, const Rect& src_r, const unsigned char* alpha, const Rect& alpha_r, |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
991 Surface* dest, const Rect& dest_r, int attribute) const |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
992 { |
0 | 993 SDL_Rect sr = SDLed(src_r); SDL_Rect dr = SDLed(dest_r); |
43
01aa5ddf7dc8
A lot of very minor improvements (deleted some unused variables, and other things like that...)
thib
parents:
32
diff
changeset
|
994 |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
995 if (attribute & PicBase::BLIT_MULTIPLY) |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
996 { |
0 | 997 DSurfaceBlitMultiply(src, src_r, dest, dest_r); |
998 return; | |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
999 } |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
1000 else if (attribute & PicBase::BLIT_ADD) |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
1001 { |
0 | 1002 unsigned char a = 255; |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
1003 if (alpha != NULL && alpha_r.width() >= 1 && alpha_r.height() >= 1) |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
1004 a = *alpha; |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
1005 DSurfaceBlitAdd(src, src_r, dest, dest_r, a); |
0 | 1006 return; |
1007 } | |
43
01aa5ddf7dc8
A lot of very minor improvements (deleted some unused variables, and other things like that...)
thib
parents:
32
diff
changeset
|
1008 |
60
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
1009 if (alpha == NULL || alpha_r.width() == 0) // simple blit |
e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
Thibaut GIRKA <thib@sitedethib.com>
parents:
53
diff
changeset
|
1010 { |
0 | 1011 SDL_BlitSurface(src, &sr, dest, &dr); |
1012 return; | |
1013 } | |
1014 if (alpha_r.width() == 1 && alpha_r.height() == 1) { | |
1015 if (*alpha == 255) { | |
1016 SDL_BlitSurface(src, &sr, dest, &dr); | |
1017 return; | |
1018 } | |
1019 if (src->format->Amask == 0) { // use per-surface alpha | |
1020 SDL_SetAlpha(src, SDL_SRCALPHA, *alpha); | |
1021 SDL_BlitSurface(src, &sr, dest, &dr); | |
1022 SDL_SetAlpha(src, 0, 0); | |
1023 return; | |
1024 } | |
1025 } | |
1026 // generic alpha blit | |
1027 DSurfaceBlitAlpha(src, src_r, dest, dest_r, alpha, alpha_r); | |
1028 } | |
1029 | |
1030 bool PicRoot::with_mask(Surface* s) { | |
1031 return s->format->Amask != 0; | |
1032 } | |
1033 | |
1034 #if USE_X11 | |
52 | 1035 #include <SDL_syswm.h> |
1036 #include <X11/Xlib.h> | |
1037 #include <X11/Xutil.h> | |
0 | 1038 #endif /* USE_X11 */ |
1039 void PicRoot::SetWindowCaption(const char* caption) { | |
1040 #if USE_X11 | |
1041 // SDL_WM_SetCaption(caption, 0); | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
60
diff
changeset
|
1042 // SDLの関数では2バイト文字をサポートしてくれないので、同等の内容に修正 |
0 | 1043 SDL_SysWMinfo info; |
1044 memset(&info,0,sizeof(info)); | |
1045 SDL_VERSION(&(info.version)); | |
1046 if (SDL_GetWMInfo(&info) == 1) { | |
1047 Display* display = info.info.x11.display; | |
1048 Window wm = info.info.x11.wmwindow; | |
1049 if (wm == 0) wm = info.info.x11.window; | |
1050 if (wm != 0) { | |
1051 XTextProperty titleprop; | |
1052 XmbTextListToTextProperty(display, (char**)&caption, 1, XCompoundTextStyle, &titleprop); | |
1053 XSetWMName(display, wm, &titleprop); | |
1054 XSetWMIconName(display, wm, &titleprop); | |
1055 XFree(titleprop.value); | |
1056 } | |
1057 XSync(display, False); | |
1058 } | |
1059 #endif /* USE_X11 */ | |
1060 } | |
1061 | |
1062 /************************************************************ | |
1063 ** PicAnm | |
1064 */ | |
1065 | |
1066 void PicBase::ClearAnm(void) { | |
1067 while(!anm.empty()) { | |
1068 delete anm.back(); | |
1069 } | |
1070 } | |
1071 PicAnm::PicAnm(PicBase* _pic) { | |
1072 pic.push_back(_pic); | |
1073 pic[0]->anm.push_back(this); | |
1074 return; | |
1075 | |
1076 } | |
1077 PicAnm::PicAnm(vector<PicBase*> _pic) : pic(_pic) { | |
1078 if (pic.empty()) return; | |
1079 pic[0]->anm.push_back(this); | |
1080 return; | |
1081 } | |
1082 PicAnm::~PicAnm() { | |
1083 vector<PicAnm*>::iterator it = find(pic[0]->anm.begin(), pic[0]->anm.end(), this); | |
1084 if (it == pic[0]->anm.end()) { | |
1085 fprintf(stderr,"Cannot found this in PicAnm::~PicAnm()"); | |
1086 } else { | |
1087 pic[0]->anm.erase(it); | |
1088 } | |
1089 } |