1 /* -*- C++ -*-
2  *
3  *  ONScripter_image.cpp - Image processing in ONScripter
4  *
5  *  Copyright (c) 2001-2019 Ogapee. All rights reserved.
6  *
7  *  ogapee@aqua.dti2.ne.jp
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "ONScripter.h"
25 #include <new>
26 #include "resize_image.h"
27 
loadImage(char * filename,bool is_flipped,bool * has_alpha,int * location,unsigned char * alpha)28 SDL_Surface *ONScripter::loadImage(char *filename, bool is_flipped, bool *has_alpha, int *location, unsigned char *alpha)
29 {
30     if (!filename) return NULL;
31 
32     SDL_Surface *tmp = NULL;
33     if (location) *location = BaseReader::ARCHIVE_TYPE_NONE;
34 
35     if (filename[0] == '>')
36         tmp = createRectangleSurface(filename, has_alpha, alpha);
37     else
38         tmp = createSurfaceFromFile(filename, has_alpha, location);
39     if (tmp == NULL) return NULL;
40 
41     if (is_flipped){
42         SDL_PixelFormat *fmt = tmp->format;
43         SDL_Surface *tmp2 = SDL_CreateRGBSurface(SDL_SWSURFACE, tmp->w, tmp->h,
44                                                  fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
45         for (int y=0; y<tmp->h; ++y) {
46             Uint32 *src = (Uint32 *)tmp->pixels + tmp->w * y;
47             Uint32 *dst = (Uint32 *)tmp2->pixels + tmp2->w * (y + 1) - 1;
48             for (int x=0; x<tmp->w; x++)
49                 *dst-- = *src++;
50         }
51         SDL_FreeSurface(tmp);
52         tmp = tmp2;
53     }
54 
55     SDL_Surface *ret;
56     if((tmp->w * tmp->format->BytesPerPixel == tmp->pitch) &&
57        (tmp->format->BitsPerPixel == image_surface->format->BitsPerPixel) &&
58        (tmp->format->Rmask == image_surface->format->Rmask) &&
59        (tmp->format->Gmask == image_surface->format->Gmask) &&
60        (tmp->format->Bmask == image_surface->format->Bmask) &&
61        (tmp->format->Amask == image_surface->format->Amask)){
62         ret = tmp;
63     }
64     else{
65         ret = SDL_ConvertSurface(tmp, image_surface->format, SDL_SWSURFACE);
66         SDL_FreeSurface(tmp);
67     }
68 
69     return ret;
70 }
71 
createRectangleSurface(char * filename,bool * has_alpha,unsigned char * alpha)72 SDL_Surface *ONScripter::createRectangleSurface(char *filename, bool *has_alpha, unsigned char *alpha)
73 {
74     int c=1, w=0, h=0;
75     bool decimal_flag = false;
76     while (filename[c] != 0x0a && filename[c] != 0x00){
77         if (!decimal_flag && filename[c] >= '0' && filename[c] <= '9')
78             w = w*10 + filename[c]-'0';
79         if (filename[c] == '.') decimal_flag = true;
80         if (filename[c] == ','){
81             c++;
82             break;
83         }
84         c++;
85     }
86 
87     decimal_flag = false;
88     while (filename[c] != 0x0a && filename[c] != 0x00){
89         if (!decimal_flag && filename[c] >= '0' && filename[c] <= '9')
90             h = h*10 + filename[c]-'0';
91         if (filename[c] == '.') decimal_flag = true;
92         if (filename[c] == ','){
93             c++;
94             break;
95         }
96         c++;
97     }
98 
99     while (filename[c] == ' ' || filename[c] == '\t') c++;
100     int n=0, c2 = c;
101     while(filename[c] == '#'){
102         uchar3 col;
103         readColor(&col, filename+c);
104         n++;
105         c += 7;
106         while (filename[c] == ' ' || filename[c] == '\t') c++;
107     }
108 
109     SDL_PixelFormat *fmt = image_surface->format;
110     SDL_Surface *tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
111                                             fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
112 
113     c = c2;
114     for (int i=0 ; i<n ; i++){
115         uchar3 col;
116         readColor(&col, filename+c);
117         c += 7;
118         while (filename[c] == ' ' || filename[c] == '\t') c++;
119 
120         SDL_Rect rect;
121         rect.x = w*i/n;
122         rect.y = 0;
123         rect.w = w*(i+1)/n - rect.x;
124         if (i == n-1) rect.w = w - rect.x;
125         rect.h = h;
126         SDL_FillRect(tmp, &rect, SDL_MapRGBA( tmp->format, col[0], col[1], col[2], alpha?*alpha:0xff));
127     }
128 
129     if (has_alpha){
130         if (fmt->Amask)
131             *has_alpha = true;
132         else
133             *has_alpha = false;
134     }
135 
136     return tmp;
137 }
138 
createSurfaceFromFile(char * filename,bool * has_alpha,int * location)139 SDL_Surface *ONScripter::createSurfaceFromFile(char *filename, bool *has_alpha, int *location)
140 {
141     unsigned long length = script_h.cBR->getFileLength( filename );
142 
143     if (length == 0){
144         fprintf( stderr, " *** can't find file [%s] ***\n", filename );
145         return NULL;
146     }
147 
148     if (filelog_flag)
149         script_h.findAndAddLog(script_h.log_info[ScriptHandler::FILE_LOG], filename, true);
150     //printf(" ... loading %s length %ld\n", filename, length );
151 
152     mean_size_of_loaded_images += length*6/5; // reserve 20% larger size
153     num_loaded_images++;
154     if (tmp_image_buf_length < mean_size_of_loaded_images/num_loaded_images){
155         tmp_image_buf_length = mean_size_of_loaded_images/num_loaded_images;
156         if (tmp_image_buf) delete[] tmp_image_buf;
157         tmp_image_buf = NULL;
158     }
159 
160     unsigned char *buffer = NULL;
161     if (length > tmp_image_buf_length){
162         buffer = new(std::nothrow) unsigned char[length];
163         if (buffer == NULL){
164             fprintf( stderr, "failed to load [%s] because file size [%lu] is too large.\n", filename, length);
165             return NULL;
166         }
167     }
168     else{
169         if (!tmp_image_buf) tmp_image_buf = new unsigned char[tmp_image_buf_length];
170         buffer = tmp_image_buf;
171     }
172 
173     script_h.cBR->getFile(filename, buffer, location);
174     char *ext = strrchr(filename, '.');
175 
176     SDL_RWops *src = SDL_RWFromMem(buffer, length);
177     int is_png = IMG_isPNG(src);
178 
179     SDL_Surface *tmp = IMG_Load_RW(src, 0);
180     if (!tmp && ext && (!strcmp(ext+1, "JPG") || !strcmp(ext+1, "jpg"))){
181         fprintf(stderr, " *** force-loading a JPG image [%s]\n", filename);
182         tmp = IMG_LoadJPG_RW(src);
183     }
184 
185     if (tmp && has_alpha){
186         if (tmp->format->Amask || is_png)
187             *has_alpha = true;
188         else
189             *has_alpha = false;
190     }
191 
192     SDL_RWclose(src);
193 
194     if (buffer != tmp_image_buf) delete[] buffer;
195 
196     if (!tmp)
197         fprintf( stderr, " *** can't load file [%s] %s ***\n", filename, IMG_GetError() );
198 
199     return tmp;
200 }
201 
202 // resize 32bit surface to 32bit surface
resizeSurface(SDL_Surface * src,SDL_Surface * dst)203 int ONScripter::resizeSurface( SDL_Surface *src, SDL_Surface *dst )
204 {
205     SDL_LockSurface( dst );
206     SDL_LockSurface( src );
207     Uint32 *src_buffer = (Uint32 *)src->pixels;
208     Uint32 *dst_buffer = (Uint32 *)dst->pixels;
209 
210     /* size of tmp_buffer must be larger than 16 bytes */
211     size_t len = src->w * (src->h+1) * 4 + 4;
212     if (resize_buffer_size < len){
213         delete[] resize_buffer;
214         resize_buffer = new unsigned char[len];
215         resize_buffer_size = len;
216     }
217     resizeImage( (unsigned char*)dst_buffer, dst->w, dst->h, dst->w * 4,
218                  (unsigned char*)src_buffer, src->w, src->h, src->w * 4,
219                  4, resize_buffer, src->w * 4, false );
220 
221     SDL_UnlockSurface( src );
222     SDL_UnlockSurface( dst );
223 
224     return 0;
225 }
226 
227 #if defined(BPP16)
228 #define BLEND_PIXEL_MASK()\
229 {\
230     Uint32 s1 = (*src1_buffer | *src1_buffer << 16) & 0x07e0f81f;\
231     Uint32 s2 = (*src2_buffer | *src2_buffer << 16) & 0x07e0f81f;\
232     Uint32 d = (s1 + ((s2 - s1) * alpha >> 5)) & 0x07e0f81f;\
233     *dst_buffer = d | d >> 16;\
234 }
235 #else
236 #define BLEND_PIXEL_MASK()\
237 {\
238     Uint32 s1 = *src1_buffer & 0xff00ff;\
239     Uint32 d1 = (s1 + ((((*src2_buffer & 0xff00ff) - s1) * alpha) >> 8));\
240     s1 = *src1_buffer & 0x00ff00;\
241     Uint32 d2 = (s1 + ((((*src2_buffer & 0x00ff00) - s1) * alpha) >> 8));\
242     *dst_buffer = (d1 & 0xff00ff) | (d2 & 0x00ff00);\
243 }
244 // Originally, the above looks like this.
245 //    mask1 = mask2 ^ 0xff;
246 //    Uint32 mask_rb = (((*src1_buffer & 0xff00ff) * mask1 +
247 //                       (*src2_buffer & 0xff00ff) * mask2) >> 8) & 0xff00ff;
248 //    Uint32 mask_g  = (((*src1_buffer & 0x00ff00) * mask1 +
249 //                       (*src2_buffer & 0x00ff00) * mask2) >> 8) & 0x00ff00;
250 #endif
251 
252 // alphaBlend
253 // dst: accumulation_surface
254 // src1: effect_src_surface
255 // src2: effect_dst_surface
alphaBlend(SDL_Surface * mask_surface,int trans_mode,Uint32 mask_value,SDL_Rect * clip)256 void ONScripter::alphaBlend( SDL_Surface *mask_surface,
257                              int trans_mode, Uint32 mask_value, SDL_Rect *clip )
258 {
259     SDL_Rect rect = screen_rect;
260     int i, j;
261 
262     /* ---------------------------------------- */
263     /* clipping */
264     if ( clip ){
265         if ( AnimationInfo::doClipping( &rect, clip ) ) return;
266     }
267 
268     /* ---------------------------------------- */
269 
270     SDL_LockSurface( effect_src_surface );
271     SDL_LockSurface( effect_dst_surface );
272     if (accumulation_surface != effect_dst_surface)
273         SDL_LockSurface( accumulation_surface );
274     if ( mask_surface ) SDL_LockSurface( mask_surface );
275 
276     ONSBuf *src1_buffer = (ONSBuf *)effect_src_surface->pixels   + effect_src_surface->w * rect.y + rect.x;
277     ONSBuf *src2_buffer = (ONSBuf *)effect_dst_surface->pixels   + effect_dst_surface->w * rect.y + rect.x;
278     ONSBuf *dst_buffer  = (ONSBuf *)accumulation_surface->pixels + accumulation_surface->w * rect.y + rect.x;
279 
280     SDL_PixelFormat *fmt = accumulation_surface->format;
281     Uint32 lowest_mask;
282     Uint8  lowest_loss;
283     if (fmt->Rmask < fmt->Bmask){
284         lowest_mask = fmt->Rmask; // ABGR8888
285         lowest_loss = fmt->Rloss;
286     }
287     else{
288         lowest_mask = fmt->Bmask; // ARGB8888 or RGB565
289         lowest_loss = fmt->Bloss;
290     }
291 
292     Uint32 overflow_mask;
293     if ( trans_mode == ALPHA_BLEND_FADE_MASK )
294         overflow_mask = 0xffffffff;
295     else
296         overflow_mask = ~lowest_mask;
297 
298     mask_value >>= lowest_loss;
299 
300     if ( (trans_mode == ALPHA_BLEND_FADE_MASK ||
301           trans_mode == ALPHA_BLEND_CROSSFADE_MASK) && mask_surface ){
302         for ( i=0; i<rect.h ; i++ ) {
303             ONSBuf *mask_buffer = (ONSBuf *)mask_surface->pixels + mask_surface->w * ((rect.y+i)%mask_surface->h);
304 
305             int j2 = rect.x;
306             for ( j=0 ; j<rect.w ; j++ ){
307                 Uint32 alpha = 0;
308                 Uint32 mask = *(mask_buffer + j2) & lowest_mask;
309                 if ( mask_value > mask ){
310                     alpha = mask_value - mask;
311                     if ( alpha & overflow_mask ) alpha = lowest_mask;
312                 }
313                 alpha++;
314                 BLEND_PIXEL_MASK();
315                 src1_buffer++; src2_buffer++; dst_buffer++;
316 
317                 if (j2 >= mask_surface->w) j2 = 0;
318                 else                       j2++;
319             }
320             src1_buffer += screen_width - rect.w;
321             src2_buffer += screen_width - rect.w;
322             dst_buffer  += screen_width - rect.w;
323         }
324     }else{ // ALPHA_BLEND_CONST
325         Uint32 alpha = (mask_value & lowest_mask) + 1;
326 
327         for ( i=0; i<rect.h ; i++ ) {
328             for ( j=rect.w ; j!=0 ; j-- ){
329                 BLEND_PIXEL_MASK();
330                 src1_buffer++; src2_buffer++; dst_buffer++;
331             }
332             src1_buffer += screen_width - rect.w;
333             src2_buffer += screen_width - rect.w;
334             dst_buffer  += screen_width - rect.w;
335         }
336     }
337 
338     if ( mask_surface ) SDL_UnlockSurface( mask_surface );
339     if (accumulation_surface != effect_dst_surface)
340         SDL_UnlockSurface( accumulation_surface );
341     SDL_UnlockSurface( effect_dst_surface );
342     SDL_UnlockSurface( effect_src_surface );
343 }
344 
345 #define BLEND_PIXEL_TEXT_BPP16()\
346 {\
347     Uint32 sa = (*src_buffer + 1) >> 3;\
348     if (sa != 0){\
349         Uint32 d = (*dst_buffer | *dst_buffer << 16) & 0x07e0f81f;\
350         d = (d + (((src_color - d) * sa) >> 5)) & 0x07e0f81f;\
351         *dst_buffer = d | d >> 16;\
352     }\
353 }
354 
355 #define BLEND_PIXEL_TEXT()\
356 {\
357     Uint32 sa = *src_buffer;\
358     if (sa == 255){\
359     	*dst_buffer = src_color3;\
360     }\
361     else if (sa != 0){\
362         sa++;\
363         Uint32 d = *dst_buffer & 0xff00ff;\
364         Uint32 d1 = (d + (((src_color1 - d) * sa) >> 8));\
365         d = *dst_buffer & 0x00ff00;\
366         Uint32 d2 = (d + (((src_color2 - d) * sa) >> 8));\
367         *dst_buffer = (d1 & 0xff00ff) | (d2 & 0x00ff00) | 0xff000000;\
368     }\
369 }
370 
371 // alphaBlendText
372 // dst: ONSBuf surface (accumulation_surface)
373 // src: 8bit surface (TTF_RenderGlyph_Shaded())
alphaBlendText(SDL_Surface * dst_surface,SDL_Rect dst_rect,SDL_Surface * src_surface,SDL_Color & color,SDL_Rect * clip,bool rotate_flag)374 void ONScripter::alphaBlendText( SDL_Surface *dst_surface, SDL_Rect dst_rect,
375                                  SDL_Surface *src_surface, SDL_Color &color, SDL_Rect *clip, bool rotate_flag )
376 {
377     int x2=0, y2=0;
378     SDL_Rect clipped_rect;
379 
380     /* ---------------------------------------- */
381     /* 1st clipping */
382     if ( clip ){
383         if ( AnimationInfo::doClipping( &dst_rect, clip, &clipped_rect ) ) return;
384 
385         x2 += clipped_rect.x;
386         y2 += clipped_rect.y;
387     }
388 
389     /* ---------------------------------------- */
390     /* 2nd clipping */
391     SDL_Rect clip_rect;
392     clip_rect.x = clip_rect.y = 0;
393     clip_rect.w = dst_surface->w;
394     clip_rect.h = dst_surface->h;
395     if ( AnimationInfo::doClipping( &dst_rect, &clip_rect, &clipped_rect ) ) return;
396 
397     x2 += clipped_rect.x;
398     y2 += clipped_rect.y;
399 
400     /* ---------------------------------------- */
401 
402     SDL_LockSurface( dst_surface );
403     SDL_LockSurface( src_surface );
404 
405     SDL_PixelFormat *fmt = dst_surface->format;
406 
407     if (fmt->BitsPerPixel == 16){
408         Uint32 src_color = (((color.r >> fmt->Rloss) << fmt->Rshift) |
409                             ((color.g >> fmt->Gloss) << fmt->Gshift) |
410                             ((color.b >> fmt->Bloss) << fmt->Bshift));
411         src_color = (src_color | src_color << 16) & 0x07e0f81f;
412 
413         Uint16 *dst_buffer = (Uint16*)dst_surface->pixels + dst_surface->w * dst_rect.y + dst_rect.x;
414 
415         if (!rotate_flag){
416             unsigned char *src_buffer = (unsigned char*)src_surface->pixels + src_surface->pitch * y2 + x2;
417             for ( int i=0 ; i<dst_rect.h ; i++ ){
418                 for ( int j=dst_rect.w ; j!=0 ; j-- ){
419                     BLEND_PIXEL_TEXT_BPP16();
420                     src_buffer++;
421                     dst_buffer++;
422                 }
423                 src_buffer += src_surface->pitch - dst_rect.w;
424                 dst_buffer += dst_surface->w - dst_rect.w;
425             }
426         }
427         else{
428             for ( int i=0 ; i<dst_rect.h ; i++ ){
429                 unsigned char *src_buffer = (unsigned char*)src_surface->pixels + src_surface->pitch*(src_surface->h - x2 - 1) + y2 + i;
430                 for ( int j=dst_rect.w ; j!=0 ; j-- ){
431                     BLEND_PIXEL_TEXT_BPP16();
432                     src_buffer -= src_surface->pitch;
433                     dst_buffer++;
434                 }
435                 dst_buffer += dst_surface->w - dst_rect.w;
436             }
437         }
438     }
439     else{
440         Uint32 src_color1 = (color.r << fmt->Rshift) | (color.b << fmt->Bshift);
441         Uint32 src_color2 = (color.g << fmt->Gshift);
442         Uint32 src_color3 = (0xff << fmt->Ashift) | src_color1 | src_color2;
443 
444         Uint32 *dst_buffer = (Uint32*)dst_surface->pixels + dst_surface->w * dst_rect.y + dst_rect.x;
445 
446         if (!rotate_flag){
447             unsigned char *src_buffer = (unsigned char*)src_surface->pixels + src_surface->pitch * y2 + x2;
448             for ( int i=0 ; i<dst_rect.h ; i++ ){
449                 for ( int j=dst_rect.w ; j!=0 ; j-- ){
450                     BLEND_PIXEL_TEXT();
451                     src_buffer++;
452                     dst_buffer++;
453                 }
454                 src_buffer += src_surface->pitch - dst_rect.w;
455                 dst_buffer += dst_surface->w - dst_rect.w;
456             }
457         }
458         else{
459             for ( int i=0 ; i<dst_rect.h ; i++ ){
460                 unsigned char *src_buffer = (unsigned char*)src_surface->pixels + src_surface->pitch*(src_surface->h - x2 - 1) + y2 + i;
461                 for ( int j=dst_rect.w ; j!=0 ; j-- ){
462                     BLEND_PIXEL_TEXT();
463                     src_buffer -= src_surface->pitch;
464                     dst_buffer++;
465                 }
466                 dst_buffer += dst_surface->w - dst_rect.w;
467             }
468         }
469     }
470 
471     SDL_UnlockSurface( src_surface );
472     SDL_UnlockSurface( dst_surface );
473 }
474 
makeNegaSurface(SDL_Surface * surface,SDL_Rect & clip)475 void ONScripter::makeNegaSurface( SDL_Surface *surface, SDL_Rect &clip )
476 {
477     SDL_LockSurface( surface );
478     ONSBuf *buf = (ONSBuf *)surface->pixels + clip.y * surface->w + clip.x;
479 
480     ONSBuf mask = surface->format->Rmask | surface->format->Gmask | surface->format->Bmask;
481     for ( int i=clip.y ; i<clip.y + clip.h ; i++ ){
482         for ( int j=clip.x ; j<clip.x + clip.w ; j++ )
483             *buf++ ^= mask;
484         buf += surface->w - clip.w;
485     }
486 
487     SDL_UnlockSurface( surface );
488 }
489 
makeMonochromeSurface(SDL_Surface * surface,SDL_Rect & clip)490 void ONScripter::makeMonochromeSurface( SDL_Surface *surface, SDL_Rect &clip )
491 {
492     SDL_LockSurface( surface );
493     ONSBuf *buf = (ONSBuf *)surface->pixels + clip.y * surface->w + clip.x, c;
494 
495     SDL_PixelFormat *fmt = surface->format;
496     for ( int i=clip.y ; i<clip.y + clip.h ; i++ ){
497         for ( int j=clip.x ; j<clip.x + clip.w ; j++ ){
498             c = ((((*buf & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss) * 77 +
499                  (((*buf & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss) * 151 +
500                  (((*buf & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss) * 28 ) >> 8;
501             *buf++ = ((monocro_color_lut[c][0] >> fmt->Rloss) << surface->format->Rshift |
502                       (monocro_color_lut[c][1] >> fmt->Gloss) << surface->format->Gshift |
503                       (monocro_color_lut[c][2] >> fmt->Bloss) << surface->format->Bshift);
504         }
505         buf += surface->w - clip.w;
506     }
507 
508     SDL_UnlockSurface( surface );
509 }
510 
511 #define FILL_LAYER_ALPHA_BUF()\
512 {\
513     for (int y=clip.y; y<clip.y+clip.h; y++){\
514         unsigned char *p = layer_alpha_buf + screen_width*y + clip.x;\
515         for (int x=clip.w; x>0; --x) *p++ = 0xff;\
516     }\
517 }
518 
refreshSurface(SDL_Surface * surface,SDL_Rect * clip_src,int refresh_mode)519 void ONScripter::refreshSurface( SDL_Surface *surface, SDL_Rect *clip_src, int refresh_mode )
520 {
521     if (refresh_mode == REFRESH_NONE_MODE) return;
522 
523     SDL_Rect clip;
524     clip.x = clip.y = 0;
525     clip.w = surface->w;
526     clip.h = surface->h;
527     if (clip_src) if ( AnimationInfo::doClipping( &clip, clip_src ) ) return;
528 
529     int i, top;
530     SDL_BlitSurface( bg_info.image_surface, &clip, surface, &clip );
531 
532     if ( !all_sprite_hide_flag ){
533         if ( z_order < 10 && refresh_mode & REFRESH_SAYA_MODE )
534             top = 9;
535         else
536             top = z_order;
537         for ( i=MAX_SPRITE_NUM-1 ; i>top ; i-- ){
538             if ( sprite_info[i].image_surface && sprite_info[i].visible ){
539                 drawTaggedSurface( surface, &sprite_info[i], clip );
540                 if (smpeg_info == &sprite_info[i])
541                     FILL_LAYER_ALPHA_BUF();
542             }
543         }
544     }
545 
546     if ( !all_sprite_hide_flag ){
547         for ( i=0 ; i<3 ; i++ ){
548             if (human_order[2-i] >= 0 && tachi_info[human_order[2-i]].image_surface)
549                 drawTaggedSurface( surface, &tachi_info[human_order[2-i]], clip );
550         }
551     }
552 
553     if ( windowback_flag ){
554         if ( nega_mode == 1 ) makeNegaSurface( surface, clip );
555         if ( monocro_flag )   makeMonochromeSurface( surface, clip );
556         if ( nega_mode == 2 ) makeNegaSurface( surface, clip );
557 
558         if (!all_sprite2_hide_flag){
559             for ( i=MAX_SPRITE2_NUM-1 ; i>=0 ; i-- ){
560                 if ( sprite2_info[i].image_surface && sprite2_info[i].visible ){
561                     drawTaggedSurface( surface, &sprite2_info[i], clip );
562                     if (smpeg_info == &sprite2_info[i])
563                         FILL_LAYER_ALPHA_BUF();
564                 }
565             }
566         }
567 
568         if (refresh_mode & REFRESH_SHADOW_MODE)
569             shadowTextDisplay( surface, clip );
570         if (refresh_mode & REFRESH_TEXT_MODE)
571             text_info.blendOnSurface( surface, 0, 0, clip, layer_alpha_buf );
572     }
573 
574     if ( !all_sprite_hide_flag ){
575         if ( refresh_mode & REFRESH_SAYA_MODE )
576             top = 10;
577         else
578             top = 0;
579         for ( i=z_order ; i>=top ; i-- ){
580             if ( sprite_info[i].image_surface && sprite_info[i].visible ){
581                 drawTaggedSurface( surface, &sprite_info[i], clip );
582                 if (smpeg_info == &sprite_info[i])
583                     FILL_LAYER_ALPHA_BUF();
584             }
585         }
586     }
587 
588     if ( !windowback_flag ){
589         if (!all_sprite2_hide_flag){
590             for ( i=MAX_SPRITE2_NUM-1 ; i>=0 ; i-- ){
591                 if ( sprite2_info[i].image_surface && sprite2_info[i].visible ){
592                     drawTaggedSurface( surface, &sprite2_info[i], clip );
593                     if (smpeg_info == &sprite2_info[i])
594                         FILL_LAYER_ALPHA_BUF();
595                 }
596             }
597         }
598 
599         if ( nega_mode == 1 ) makeNegaSurface( surface, clip );
600         if ( monocro_flag )   makeMonochromeSurface( surface, clip );
601         if ( nega_mode == 2 ) makeNegaSurface( surface, clip );
602     }
603 
604     if ( !( refresh_mode & REFRESH_SAYA_MODE ) ){
605         for ( i=0 ; i<MAX_PARAM_NUM ; i++ ){
606             if ( bar_info[i] )
607                 drawTaggedSurface( surface, bar_info[i], clip );
608         }
609         for ( i=0 ; i<MAX_PARAM_NUM ; i++ ){
610             if ( prnum_info[i] )
611                 drawTaggedSurface( surface, prnum_info[i], clip );
612         }
613     }
614 
615     if ( !windowback_flag ){
616         if (refresh_mode & REFRESH_SHADOW_MODE)
617             shadowTextDisplay( surface, clip );
618         if (refresh_mode & REFRESH_TEXT_MODE)
619             text_info.blendOnSurface( surface, 0, 0, clip, layer_alpha_buf );
620     }
621 
622     if ( refresh_mode & REFRESH_CURSOR_MODE && !textgosub_label ){
623         if ( clickstr_state == CLICK_WAIT )
624             drawTaggedSurface( surface, &cursor_info[0], clip );
625         else if ( clickstr_state == CLICK_NEWPAGE )
626             drawTaggedSurface( surface, &cursor_info[1], clip );
627     }
628 
629     if (show_dialog_flag)
630         drawTaggedSurface( surface, &dialog_info, clip );
631 
632     ButtonLink *bl = root_button_link.next;
633     while( bl ){
634         if (bl->show_flag > 0)
635             drawTaggedSurface( surface, bl->anim[bl->show_flag-1], clip );
636         bl = bl->next;
637     }
638 }
639 
refreshSprite(int sprite_no,bool active_flag,int cell_no,SDL_Rect * check_src_rect,SDL_Rect * check_dst_rect)640 void ONScripter::refreshSprite( int sprite_no, bool active_flag, int cell_no,
641                                 SDL_Rect *check_src_rect, SDL_Rect *check_dst_rect )
642 {
643     if ( sprite_info[sprite_no].image_surface &&
644          ( sprite_info[ sprite_no ].visible != active_flag ||
645            (cell_no >= 0 && sprite_info[ sprite_no ].current_cell != cell_no ) ||
646            AnimationInfo::doClipping(check_src_rect, &sprite_info[ sprite_no ].pos) == 0 ||
647            AnimationInfo::doClipping(check_dst_rect, &sprite_info[ sprite_no ].pos) == 0) )
648     {
649         if ( cell_no >= 0 )
650             sprite_info[ sprite_no ].setCell(cell_no);
651 
652         sprite_info[ sprite_no ].visible = active_flag;
653 
654         dirty_rect.add( sprite_info[ sprite_no ].pos );
655     }
656 }
657 
createBackground()658 void ONScripter::createBackground()
659 {
660     bg_info.num_of_cells = 1;
661     bg_info.trans_mode = AnimationInfo::TRANS_COPY;
662     bg_info.pos.x = 0;
663     bg_info.pos.y = 0;
664     bg_info.allocImage( screen_width, screen_height, texture_format );
665 
666     if ( !strcmp( bg_info.file_name, "white" ) ){
667         bg_info.color[0] = bg_info.color[1] = bg_info.color[2] = 0xff;
668     }
669     else if ( !strcmp( bg_info.file_name, "black" ) ||
670               !strcmp( bg_info.file_name, "*bgcpy" ) ){
671         bg_info.color[0] = bg_info.color[1] = bg_info.color[2] = 0x00;
672     }
673     else if ( bg_info.file_name[0] == '#' ){
674             readColor( &bg_info.color, bg_info.file_name );
675     }
676     else{
677         AnimationInfo anim;
678         setStr( &anim.image_name, bg_info.file_name );
679         parseTaggedString( &anim );
680         anim.trans_mode = AnimationInfo::TRANS_COPY;
681         setupAnimationInfo( &anim );
682 
683         bg_info.fill(0, 0, 0, 0xff);
684         if (anim.image_surface){
685             SDL_Rect src_rect;
686             src_rect.x = src_rect.y = 0;
687             src_rect.w = anim.image_surface->w;
688             src_rect.h = anim.image_surface->h;
689             SDL_Rect dst_rect = {0, 0};
690             if (screen_width >= anim.image_surface->w){
691                 dst_rect.x = (screen_width - anim.image_surface->w) / 2;
692             }
693             else{
694                 src_rect.x = (anim.image_surface->w - screen_width) / 2;
695                 src_rect.w = screen_width;
696             }
697 
698             if (screen_height >= anim.image_surface->h){
699                 dst_rect.y = (screen_height - anim.image_surface->h) / 2;
700             }
701             else{
702                 src_rect.y = (anim.image_surface->h - screen_height) / 2;
703                 src_rect.h = screen_height;
704             }
705             bg_info.copySurface(anim.image_surface, &src_rect, &dst_rect);
706         }
707         return;
708     }
709 
710     bg_info.fill(bg_info.color[0], bg_info.color[1], bg_info.color[2], 0xff);
711 }
712