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