splash.cpp

Go to the documentation of this file.
00001 /* $Id: splash.cpp 26209 2014-01-02 22:41:58Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "../../stdafx.h"
00013 #include "../../openttd.h"
00014 #include "../../debug.h"
00015 #include "../../gfx_func.h"
00016 #include "../../fileio_func.h"
00017 #include "../../blitter/factory.hpp"
00018 #include "../../core/mem_func.hpp"
00019 
00020 #include "splash.h"
00021 
00022 #ifdef WITH_PNG
00023 
00024 #include <png.h>
00025 
00032 static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message)
00033 {
00034   DEBUG(misc, 0, "[libpng] error: %s - %s", message, (char *)png_get_error_ptr(png_ptr));
00035   longjmp(png_jmpbuf(png_ptr), 1);
00036 }
00037 
00044 static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message)
00045 {
00046   DEBUG(misc, 1, "[libpng] warning: %s - %s", message, (char *)png_get_error_ptr(png_ptr));
00047 }
00048 
00052 void DisplaySplashImage()
00053 {
00054   FILE *f = FioFOpenFile(SPLASH_IMAGE_FILE, "r", BASESET_DIR);
00055   if (f == NULL) return;
00056 
00057   png_byte header[8];
00058   fread(header, sizeof(png_byte), 8, f);
00059   if (png_sig_cmp(header, 0, 8) != 0) {
00060     fclose(f);
00061     return;
00062   }
00063 
00064   png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, png_my_error, png_my_warning);
00065 
00066   if (png_ptr == NULL) {
00067     fclose(f);
00068     return;
00069   }
00070 
00071   png_infop info_ptr = png_create_info_struct(png_ptr);
00072   if (info_ptr == NULL) {
00073     png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
00074     fclose(f);
00075     return;
00076   }
00077 
00078   png_infop end_info = png_create_info_struct(png_ptr);
00079   if (end_info == NULL) {
00080     png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00081     fclose(f);
00082     return;
00083   }
00084 
00085   if (setjmp(png_jmpbuf(png_ptr))) {
00086     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00087     fclose(f);
00088     return;
00089   }
00090 
00091   png_init_io(png_ptr, f);
00092   png_set_sig_bytes(png_ptr, 8);
00093 
00094   png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
00095 
00096   uint width      = png_get_image_width(png_ptr, info_ptr);
00097   uint height     = png_get_image_height(png_ptr, info_ptr);
00098   uint bit_depth  = png_get_bit_depth(png_ptr, info_ptr);
00099   uint color_type = png_get_color_type(png_ptr, info_ptr);
00100 
00101   if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) {
00102     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00103     fclose(f);
00104     return;
00105   }
00106 
00107   if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) {
00108     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00109     fclose(f);
00110     return;
00111   }
00112 
00113   png_colorp palette;
00114   int num_palette;
00115   png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
00116 
00117   png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);
00118 
00119   if (width > (uint) _screen.width) width = _screen.width;
00120   if (height > (uint) _screen.height) height = _screen.height;
00121 
00122   uint xoff = (_screen.width - width) / 2;
00123   uint yoff = (_screen.height - height) / 2;
00124 
00125   switch (BlitterFactory::GetCurrentBlitter()->GetScreenDepth()) {
00126     case 8: {
00127         uint8 *dst_ptr = (uint8 *)_screen.dst_ptr;
00128         /* Initialize buffer */
00129         MemSetT(dst_ptr, 0xff, _screen.pitch * _screen.height);
00130 
00131         for (uint y = 0; y < height; y++) {
00132           uint8 *src = row_pointers[y];
00133           uint8 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;
00134 
00135           memcpy(dst, src, width);
00136         }
00137 
00138         for (int i = 0; i < num_palette; i++) {
00139           _cur_palette.palette[i].a = i == 0 ? 0 : 0xff;
00140           _cur_palette.palette[i].r = palette[i].red;
00141           _cur_palette.palette[i].g = palette[i].green;
00142           _cur_palette.palette[i].b = palette[i].blue;
00143         }
00144 
00145         _cur_palette.palette[0xff].a = 0xff;
00146         _cur_palette.palette[0xff].r = 0;
00147         _cur_palette.palette[0xff].g = 0;
00148         _cur_palette.palette[0xff].b = 0;
00149 
00150         _cur_palette.first_dirty = 0;
00151         _cur_palette.count_dirty = 256;
00152         break;
00153       }
00154     case 32: {
00155         uint32 *dst_ptr = (uint32 *)_screen.dst_ptr;
00156         /* Initialize buffer */
00157         MemSetT(dst_ptr, 0, _screen.pitch * _screen.height);
00158 
00159         for (uint y = 0; y < height; y++) {
00160           uint8 *src = row_pointers[y];
00161           uint32 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;
00162 
00163           for (uint x = 0; x < width; x++) {
00164             dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000;
00165           }
00166         }
00167         break;
00168       }
00169   }
00170 
00171   png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00172   fclose(f);
00173   return;
00174 }
00175 
00176 
00177 
00178 #else /* WITH_PNG */
00179 
00183 void DisplaySplashImage() {}
00184 
00185 #endif /* WITH_PNG */