OpenTTD
splash.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * 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.
4  * 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.
5  * 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/>.
6  */
7 
10 #include "../../stdafx.h"
11 #include "../../openttd.h"
12 #include "../../debug.h"
13 #include "../../gfx_func.h"
14 #include "../../fileio_func.h"
15 #include "../../blitter/factory.hpp"
16 #include "../../core/mem_func.hpp"
17 
18 #include "splash.h"
19 
20 #ifdef WITH_PNG
21 
22 #include <png.h>
23 
24 #include "../../safeguards.h"
25 
32 static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message)
33 {
34  DEBUG(misc, 0, "[libpng] error: %s - %s", message, (char *)png_get_error_ptr(png_ptr));
35  longjmp(png_jmpbuf(png_ptr), 1);
36 }
37 
44 static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message)
45 {
46  DEBUG(misc, 1, "[libpng] warning: %s - %s", message, (char *)png_get_error_ptr(png_ptr));
47 }
48 
53 {
54  FILE *f = FioFOpenFile(SPLASH_IMAGE_FILE, "r", BASESET_DIR);
55  if (f == nullptr) return;
56 
57  png_byte header[8];
58  fread(header, sizeof(png_byte), 8, f);
59  if (png_sig_cmp(header, 0, 8) != 0) {
60  fclose(f);
61  return;
62  }
63 
64  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) nullptr, png_my_error, png_my_warning);
65 
66  if (png_ptr == nullptr) {
67  fclose(f);
68  return;
69  }
70 
71  png_infop info_ptr = png_create_info_struct(png_ptr);
72  if (info_ptr == nullptr) {
73  png_destroy_read_struct(&png_ptr, (png_infopp)nullptr, (png_infopp)nullptr);
74  fclose(f);
75  return;
76  }
77 
78  png_infop end_info = png_create_info_struct(png_ptr);
79  if (end_info == nullptr) {
80  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)nullptr);
81  fclose(f);
82  return;
83  }
84 
85  if (setjmp(png_jmpbuf(png_ptr))) {
86  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
87  fclose(f);
88  return;
89  }
90 
91  png_init_io(png_ptr, f);
92  png_set_sig_bytes(png_ptr, 8);
93 
94  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
95 
96  uint width = png_get_image_width(png_ptr, info_ptr);
97  uint height = png_get_image_height(png_ptr, info_ptr);
98  uint bit_depth = png_get_bit_depth(png_ptr, info_ptr);
99  uint color_type = png_get_color_type(png_ptr, info_ptr);
100 
101  if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) {
102  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
103  fclose(f);
104  return;
105  }
106 
107  if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) {
108  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
109  fclose(f);
110  return;
111  }
112 
113  png_colorp palette;
114  int num_palette;
115  png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
116 
117  png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);
118 
119  if (width > (uint) _screen.width) width = _screen.width;
120  if (height > (uint) _screen.height) height = _screen.height;
121 
122  uint xoff = (_screen.width - width) / 2;
123  uint yoff = (_screen.height - height) / 2;
124 
126  case 8: {
127  uint8 *dst_ptr = (uint8 *)_screen.dst_ptr;
128  /* Initialize buffer */
129  MemSetT(dst_ptr, 0xff, _screen.pitch * _screen.height);
130 
131  for (uint y = 0; y < height; y++) {
132  uint8 *src = row_pointers[y];
133  uint8 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;
134 
135  memcpy(dst, src, width);
136  }
137 
138  for (int i = 0; i < num_palette; i++) {
139  _cur_palette.palette[i].a = i == 0 ? 0 : 0xff;
140  _cur_palette.palette[i].r = palette[i].red;
141  _cur_palette.palette[i].g = palette[i].green;
142  _cur_palette.palette[i].b = palette[i].blue;
143  }
144 
145  _cur_palette.palette[0xff].a = 0xff;
146  _cur_palette.palette[0xff].r = 0;
147  _cur_palette.palette[0xff].g = 0;
148  _cur_palette.palette[0xff].b = 0;
149 
152  break;
153  }
154  case 32: {
155  uint32 *dst_ptr = (uint32 *)_screen.dst_ptr;
156  /* Initialize buffer */
157  MemSetT(dst_ptr, 0, _screen.pitch * _screen.height);
158 
159  for (uint y = 0; y < height; y++) {
160  uint8 *src = row_pointers[y];
161  uint32 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;
162 
163  for (uint x = 0; x < width; x++) {
164  dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000;
165  }
166  }
167  break;
168  }
169  }
170 
171  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
172  fclose(f);
173  return;
174 }
175 
176 
177 
178 #else /* WITH_PNG */
179 
183 void DisplaySplashImage() {}
184 
185 #endif /* WITH_PNG */
static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message)
Handle warning in pnglib.
Definition: splash.cpp:44
Colour palette[256]
Current palette. Entry 0 has to be always fully transparent!
Definition: gfx_type.h:309
Functions to support splash screens for OSX.
uint8 a
colour channels in LE order
Definition: gfx_type.h:168
void DisplaySplashImage()
Display a splash image shown on startup (WITH_PNG).
Definition: splash.cpp:52
static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message)
Handle pnglib error.
Definition: splash.cpp:32
Subdirectory for all base data (base sets, intro game)
Definition: fileio_type.h:116
FILE * FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Definition: fileio.cpp:463
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition: factory.hpp:145
int first_dirty
The first dirty element.
Definition: gfx_type.h:310
Palette _cur_palette
Current palette.
Definition: gfx.cpp:48
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
virtual uint8 GetScreenDepth()=0
Get the screen depth this blitter works for.
int count_dirty
The number of dirty elements.
Definition: gfx_type.h:311
static void MemSetT(T *ptr, byte value, size_t num=1)
Type-safe version of memset().
Definition: mem_func.hpp:49