Mercurial > otakunoraifu
annotate window/picture.cc @ 60:e16e13d8cd68
Replaced SATURATE -> ADD, implemented objComposite, corrected minor things
author | Thibaut GIRKA <thib@sitedethib.com> |
---|---|
date | Fri, 18 Dec 2009 20:41:38 +0100 |
parents | ddbcbd000206 |
children | 4416cfac86ae |
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); |
48 void DSurfaceFill(Surface* src, const Rect& rect, int r, int g, int b, int a=0xff); // クリア | |
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; |
104 if (parent) { // 自分を親から削除 | |
105 parent->children.remove(this); | |
106 // root の update 情報から自分を削除 | |
107 parent->Root().DeleteUpdatePic(this); | |
108 // 自分の領域を書き直す | |
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) { |
116 // 実際に描画する領域を得る | |
117 Rect rpos = rpos_orig; | |
118 // 親widget上に設定されたclip area 内に描画を限定する | |
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; | |
126 // 必要に応じて保存、描画 | |
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); | |
137 } else if (parent == 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) { |
147 // 実際に描画する領域を得る | |
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 } | |
165 // 親の座標に変換後、Query する | |
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 } | |
203 // move_to と zpos のうち、後ろの方の picture から書きなおす必要がある | |
204 iterator redraw_zpos = z_pos; redraw_zpos++; | |
205 if (move_to == ZMOVE_BOTTOM) { // 最背面へ | |
206 parent->children.erase(z_pos); | |
207 parent->children.push_front(this); | |
208 z_pos = parent->children.begin(); | |
209 redraw_zpos = parent->children.begin(); | |
210 } else if (move_to == ZMOVE_TOP) { // 最前面へ | |
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(); | |
227 /* @@@ parent->Blit() と Blit() の違いが分からないので修正 06/12/02 | |
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) { |
275 /* 自分の親がすべて shown か? */ | |
276 PicContainer* cur; | |
277 for (cur = parent; cur != 0; cur = cur->parent) | |
278 if (cur->is_hidden) break; | |
52 | 279 if (cur != NULL) { // 親が隠れているので表示はしない |
0 | 280 is_hidden = false; |
281 is_hidden_now = true; | |
282 return; | |
283 } | |
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 | |
333 /* ファイルを元に alpha 画像を作成する */ | |
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; | |
352 if ( ((SDL_Surface*)surface_own)->format->Amask == 0) { // mask を surface に繰り込む | |
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)); | |
374 } else { // 外部にマスク作成 | |
375 /* マスクのうち、0xff であるべき部分を画像から判別、変更する */ | |
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) { | |
409 // surface の大きさに自分の大きさを変更 | |
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++; | |
52 | 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; | |
505 // cache されている領域を探す | |
506 // z自身がキャッシュしていれば、ここで終了 | |
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 } | |
513 // z より下の子がキャッシュ、あるいは SOLID 描画できないか? | |
514 for (it = z; it != begin;) { // 子がcontainerの場合のチェックは省略 | |
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 } | |
529 // 自分自身がキャッシュ、あるいは SOLID 描画できないか? | |
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: | |
547 BlitSelf(rpos); // 子は描画せず、自分だけ描画 | |
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) { |
589 // 実際に描画する領域を得る | |
590 rpos.intersect(Rect(0, 0, rel_pos.width(), rel_pos.height())); | |
591 if (rpos.empty()) return; | |
592 Rect apos = QueryAbsPos(rpos); | |
593 // 必要に応じて保存、描画 | |
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); | |
52 | 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 |
0 | 631 void PicContainer::RMove(int add_x, int add_y) { // event widget の移動があり得るので子についてもRMoveを呼び出す |
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; | |
727 count_max = 32; // キャッシュ量(決め打ち) | |
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; | |
764 if (is_mask == ALPHA_MASK) { // alpha がすべて 0xff ならマスク無しとする | |
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 |
790 while (count >= count_max) { // count_max 以上のデータを可能なら削除する | |
791 qiterator it; | |
792 for (it=queue.begin(); it != queue.end(); it++) { | |
793 if (DeleteData(*it)) break; | |
794 } | |
795 if (it == queue.end()) break; // 全データが使用中なら終了 | |
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() { |
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) { |
880 /* 共通する領域を消去する */ | |
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)) { | |
894 if (jt->pic == pic || jt->pic->IsParent(pic)) { // 親が共通、かつ領域も共通 | |
895 jt->rpos = Rect(0,0); // empty rect をセット | |
896 jt->apos = Rect(0,0); | |
897 } | |
898 } else if (jt->apos.is_inner(apos)) { // 相手に自分が包含される | |
899 if (jt->pic == pic || jt->pic->IsParent(pic)) { // 親が共通、かつ領域も共通 | |
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 } | |
958 /* xkanon の残骸 */ | |
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); | |
1042 // SDLの関数では2バイト文字をサポートしてくれないので、同等の内容に修正 | |
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 } |