gosu 2.0.0.pre6 → 2.0.0.pre8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/dependencies/SDL/include/SDL.h +1 -1
  3. data/dependencies/SDL/include/SDL_assert.h +3 -1
  4. data/dependencies/SDL/include/SDL_atomic.h +2 -2
  5. data/dependencies/SDL/include/SDL_audio.h +1 -1
  6. data/dependencies/SDL/include/SDL_bits.h +1 -1
  7. data/dependencies/SDL/include/SDL_blendmode.h +3 -3
  8. data/dependencies/SDL/include/SDL_clipboard.h +1 -1
  9. data/dependencies/SDL/include/SDL_config.h +1 -1
  10. data/dependencies/SDL/include/SDL_cpuinfo.h +1 -1
  11. data/dependencies/SDL/include/SDL_egl.h +1 -1
  12. data/dependencies/SDL/include/SDL_endian.h +1 -1
  13. data/dependencies/SDL/include/SDL_error.h +1 -1
  14. data/dependencies/SDL/include/SDL_events.h +4 -11
  15. data/dependencies/SDL/include/SDL_filesystem.h +3 -3
  16. data/dependencies/SDL/include/SDL_gamecontroller.h +27 -5
  17. data/dependencies/SDL/include/SDL_gesture.h +1 -1
  18. data/dependencies/SDL/include/SDL_guid.h +1 -1
  19. data/dependencies/SDL/include/SDL_haptic.h +1 -1
  20. data/dependencies/SDL/include/SDL_hidapi.h +1 -1
  21. data/dependencies/SDL/include/SDL_hints.h +268 -1
  22. data/dependencies/SDL/include/SDL_joystick.h +1 -1
  23. data/dependencies/SDL/include/SDL_keyboard.h +5 -3
  24. data/dependencies/SDL/include/SDL_keycode.h +1 -1
  25. data/dependencies/SDL/include/SDL_loadso.h +1 -1
  26. data/dependencies/SDL/include/SDL_locale.h +1 -1
  27. data/dependencies/SDL/include/SDL_log.h +3 -3
  28. data/dependencies/SDL/include/SDL_main.h +1 -1
  29. data/dependencies/SDL/include/SDL_messagebox.h +1 -1
  30. data/dependencies/SDL/include/SDL_metal.h +1 -1
  31. data/dependencies/SDL/include/SDL_misc.h +1 -1
  32. data/dependencies/SDL/include/SDL_mouse.h +1 -1
  33. data/dependencies/SDL/include/SDL_mutex.h +1 -1
  34. data/dependencies/SDL/include/SDL_name.h +1 -1
  35. data/dependencies/SDL/include/SDL_opengl.h +1 -1
  36. data/dependencies/SDL/include/SDL_opengles.h +1 -1
  37. data/dependencies/SDL/include/SDL_opengles2.h +1 -1
  38. data/dependencies/SDL/include/SDL_pixels.h +20 -2
  39. data/dependencies/SDL/include/SDL_platform.h +7 -1
  40. data/dependencies/SDL/include/SDL_power.h +1 -1
  41. data/dependencies/SDL/include/SDL_quit.h +1 -1
  42. data/dependencies/SDL/include/SDL_rect.h +1 -1
  43. data/dependencies/SDL/include/SDL_render.h +3 -3
  44. data/dependencies/SDL/include/SDL_revision.h +2 -2
  45. data/dependencies/SDL/include/SDL_rwops.h +1 -1
  46. data/dependencies/SDL/include/SDL_scancode.h +1 -1
  47. data/dependencies/SDL/include/SDL_sensor.h +1 -1
  48. data/dependencies/SDL/include/SDL_shape.h +1 -1
  49. data/dependencies/SDL/include/SDL_stdinc.h +18 -12
  50. data/dependencies/SDL/include/SDL_surface.h +1 -1
  51. data/dependencies/SDL/include/SDL_system.h +17 -2
  52. data/dependencies/SDL/include/SDL_syswm.h +1 -1
  53. data/dependencies/SDL/include/SDL_test.h +1 -1
  54. data/dependencies/SDL/include/SDL_test_assert.h +1 -1
  55. data/dependencies/SDL/include/SDL_test_common.h +1 -1
  56. data/dependencies/SDL/include/SDL_test_compare.h +1 -1
  57. data/dependencies/SDL/include/SDL_test_crc32.h +1 -1
  58. data/dependencies/SDL/include/SDL_test_font.h +1 -1
  59. data/dependencies/SDL/include/SDL_test_fuzzer.h +1 -1
  60. data/dependencies/SDL/include/SDL_test_harness.h +1 -1
  61. data/dependencies/SDL/include/SDL_test_images.h +1 -1
  62. data/dependencies/SDL/include/SDL_test_log.h +1 -1
  63. data/dependencies/SDL/include/SDL_test_md5.h +1 -1
  64. data/dependencies/SDL/include/SDL_test_memory.h +1 -1
  65. data/dependencies/SDL/include/SDL_test_random.h +1 -1
  66. data/dependencies/SDL/include/SDL_thread.h +1 -1
  67. data/dependencies/SDL/include/SDL_timer.h +1 -1
  68. data/dependencies/SDL/include/SDL_touch.h +1 -1
  69. data/dependencies/SDL/include/SDL_types.h +1 -1
  70. data/dependencies/SDL/include/SDL_version.h +3 -3
  71. data/dependencies/SDL/include/SDL_video.h +8 -2
  72. data/dependencies/SDL/include/begin_code.h +3 -1
  73. data/dependencies/SDL/include/close_code.h +1 -1
  74. data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
  75. data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
  76. data/dependencies/SDL_sound/SDL_sound_vorbis.c +6 -3
  77. data/dependencies/SDL_sound/dr_flac.h +9 -5
  78. data/dependencies/SDL_sound/dr_mp3.h +14 -3
  79. data/dependencies/SDL_sound/stb_vorbis.h +66 -20
  80. data/dependencies/stb/stb_image.h +173 -175
  81. data/ext/gosu-ffi/gosu-ffi.def +1 -0
  82. data/ffi/Gosu_FFI_internal.h +2 -2
  83. data/ffi/Gosu_Image.cpp +26 -14
  84. data/ffi/Gosu_Image.h +8 -2
  85. data/include/Gosu/Image.hpp +1 -1
  86. data/lib/SDL2.dll +0 -0
  87. data/lib/gosu/ffi.rb +2 -1
  88. data/lib/gosu/image.rb +33 -20
  89. data/lib64/SDL2.dll +0 -0
  90. data/src/BinPacker.cpp +1 -1
  91. data/src/ClipRectStack.cpp +38 -0
  92. data/src/ClipRectStack.hpp +17 -83
  93. data/src/DrawOp.hpp +0 -5
  94. data/src/DrawOpQueue.hpp +24 -30
  95. data/src/GosuGLView.cpp +1 -7
  96. data/src/Graphics.cpp +8 -5
  97. data/src/GraphicsImpl.hpp +0 -23
  98. data/src/RenderState.hpp +25 -38
  99. metadata +6 -5
@@ -1,4 +1,4 @@
1
- /* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
1
+ /* stb_image - v2.29 - public domain image loader - http://nothings.org/stb
2
2
  no warranty implied; use at your own risk
3
3
 
4
4
  Do this:
@@ -48,6 +48,7 @@ LICENSE
48
48
 
49
49
  RECENT REVISION HISTORY:
50
50
 
51
+ 2.29 (2023-05-xx) optimizations
51
52
  2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
52
53
  2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
53
54
  2.26 (2020-07-13) many minor fixes
@@ -1072,8 +1073,8 @@ static int stbi__addints_valid(int a, int b)
1072
1073
  return a <= INT_MAX - b;
1073
1074
  }
1074
1075
 
1075
- // returns 1 if the product of two signed shorts is valid, 0 on overflow.
1076
- static int stbi__mul2shorts_valid(short a, short b)
1076
+ // returns 1 if the product of two ints fits in a signed short, 0 on overflow.
1077
+ static int stbi__mul2shorts_valid(int a, int b)
1077
1078
  {
1078
1079
  if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
1079
1080
  if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
@@ -3384,13 +3385,13 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
3384
3385
  return 1;
3385
3386
  }
3386
3387
 
3387
- static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
3388
+ static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
3388
3389
  {
3389
3390
  // some JPEGs have junk at end, skip over it but if we find what looks
3390
3391
  // like a valid marker, resume there
3391
3392
  while (!stbi__at_eof(j->s)) {
3392
- int x = stbi__get8(j->s);
3393
- while (x == 255) { // might be a marker
3393
+ stbi_uc x = stbi__get8(j->s);
3394
+ while (x == 0xff) { // might be a marker
3394
3395
  if (stbi__at_eof(j->s)) return STBI__MARKER_none;
3395
3396
  x = stbi__get8(j->s);
3396
3397
  if (x != 0x00 && x != 0xff) {
@@ -4176,6 +4177,7 @@ typedef struct
4176
4177
  {
4177
4178
  stbi_uc *zbuffer, *zbuffer_end;
4178
4179
  int num_bits;
4180
+ int hit_zeof_once;
4179
4181
  stbi__uint32 code_buffer;
4180
4182
 
4181
4183
  char *zout;
@@ -4242,9 +4244,20 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
4242
4244
  int b,s;
4243
4245
  if (a->num_bits < 16) {
4244
4246
  if (stbi__zeof(a)) {
4245
- return -1; /* report error for unexpected end of data. */
4247
+ if (!a->hit_zeof_once) {
4248
+ // This is the first time we hit eof, insert 16 extra padding btis
4249
+ // to allow us to keep going; if we actually consume any of them
4250
+ // though, that is invalid data. This is caught later.
4251
+ a->hit_zeof_once = 1;
4252
+ a->num_bits += 16; // add 16 implicit zero bits
4253
+ } else {
4254
+ // We already inserted our extra 16 padding bits and are again
4255
+ // out, this stream is actually prematurely terminated.
4256
+ return -1;
4257
+ }
4258
+ } else {
4259
+ stbi__fill_bits(a);
4246
4260
  }
4247
- stbi__fill_bits(a);
4248
4261
  }
4249
4262
  b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
4250
4263
  if (b) {
@@ -4309,6 +4322,13 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
4309
4322
  int len,dist;
4310
4323
  if (z == 256) {
4311
4324
  a->zout = zout;
4325
+ if (a->hit_zeof_once && a->num_bits < 16) {
4326
+ // The first time we hit zeof, we inserted 16 extra zero bits into our bit
4327
+ // buffer so the decoder can just do its speculative decoding. But if we
4328
+ // actually consumed any of those bits (which is the case when num_bits < 16),
4329
+ // the stream actually read past the end so it is malformed.
4330
+ return stbi__err("unexpected end","Corrupt PNG");
4331
+ }
4312
4332
  return 1;
4313
4333
  }
4314
4334
  if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
@@ -4320,7 +4340,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
4320
4340
  dist = stbi__zdist_base[z];
4321
4341
  if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
4322
4342
  if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
4323
- if (zout + len > a->zout_end) {
4343
+ if (len > a->zout_end - zout) {
4324
4344
  if (!stbi__zexpand(a, zout, len)) return 0;
4325
4345
  zout = a->zout;
4326
4346
  }
@@ -4464,6 +4484,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
4464
4484
  if (!stbi__parse_zlib_header(a)) return 0;
4465
4485
  a->num_bits = 0;
4466
4486
  a->code_buffer = 0;
4487
+ a->hit_zeof_once = 0;
4467
4488
  do {
4468
4489
  final = stbi__zreceive(a,1);
4469
4490
  type = stbi__zreceive(a,2);
@@ -4619,9 +4640,8 @@ enum {
4619
4640
  STBI__F_up=2,
4620
4641
  STBI__F_avg=3,
4621
4642
  STBI__F_paeth=4,
4622
- // synthetic filters used for first scanline to avoid needing a dummy row of 0s
4623
- STBI__F_avg_first,
4624
- STBI__F_paeth_first
4643
+ // synthetic filter used for first scanline to avoid needing a dummy row of 0s
4644
+ STBI__F_avg_first
4625
4645
  };
4626
4646
 
4627
4647
  static stbi_uc first_row_filter[5] =
@@ -4630,29 +4650,56 @@ static stbi_uc first_row_filter[5] =
4630
4650
  STBI__F_sub,
4631
4651
  STBI__F_none,
4632
4652
  STBI__F_avg_first,
4633
- STBI__F_paeth_first
4653
+ STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub
4634
4654
  };
4635
4655
 
4636
4656
  static int stbi__paeth(int a, int b, int c)
4637
4657
  {
4638
- int p = a + b - c;
4639
- int pa = abs(p-a);
4640
- int pb = abs(p-b);
4641
- int pc = abs(p-c);
4642
- if (pa <= pb && pa <= pc) return a;
4643
- if (pb <= pc) return b;
4644
- return c;
4658
+ // This formulation looks very different from the reference in the PNG spec, but is
4659
+ // actually equivalent and has favorable data dependencies and admits straightforward
4660
+ // generation of branch-free code, which helps performance significantly.
4661
+ int thresh = c*3 - (a + b);
4662
+ int lo = a < b ? a : b;
4663
+ int hi = a < b ? b : a;
4664
+ int t0 = (hi <= thresh) ? lo : c;
4665
+ int t1 = (thresh <= lo) ? hi : t0;
4666
+ return t1;
4645
4667
  }
4646
4668
 
4647
4669
  static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
4648
4670
 
4671
+ // adds an extra all-255 alpha channel
4672
+ // dest == src is legal
4673
+ // img_n must be 1 or 3
4674
+ static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n)
4675
+ {
4676
+ int i;
4677
+ // must process data backwards since we allow dest==src
4678
+ if (img_n == 1) {
4679
+ for (i=x-1; i >= 0; --i) {
4680
+ dest[i*2+1] = 255;
4681
+ dest[i*2+0] = src[i];
4682
+ }
4683
+ } else {
4684
+ STBI_ASSERT(img_n == 3);
4685
+ for (i=x-1; i >= 0; --i) {
4686
+ dest[i*4+3] = 255;
4687
+ dest[i*4+2] = src[i*3+2];
4688
+ dest[i*4+1] = src[i*3+1];
4689
+ dest[i*4+0] = src[i*3+0];
4690
+ }
4691
+ }
4692
+ }
4693
+
4649
4694
  // create the png data from post-deflated data
4650
4695
  static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
4651
4696
  {
4652
- int bytes = (depth == 16? 2 : 1);
4697
+ int bytes = (depth == 16 ? 2 : 1);
4653
4698
  stbi__context *s = a->s;
4654
4699
  stbi__uint32 i,j,stride = x*out_n*bytes;
4655
4700
  stbi__uint32 img_len, img_width_bytes;
4701
+ stbi_uc *filter_buf;
4702
+ int all_ok = 1;
4656
4703
  int k;
4657
4704
  int img_n = s->img_n; // copy it into a local for later
4658
4705
 
@@ -4664,8 +4711,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
4664
4711
  a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
4665
4712
  if (!a->out) return stbi__err("outofmem", "Out of memory");
4666
4713
 
4714
+ // note: error exits here don't need to clean up a->out individually,
4715
+ // stbi__do_png always does on error.
4667
4716
  if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
4668
4717
  img_width_bytes = (((img_n * x * depth) + 7) >> 3);
4718
+ if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG");
4669
4719
  img_len = (img_width_bytes + 1) * y;
4670
4720
 
4671
4721
  // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
@@ -4673,189 +4723,137 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
4673
4723
  // so just check for raw_len < img_len always.
4674
4724
  if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
4675
4725
 
4726
+ // Allocate two scan lines worth of filter workspace buffer.
4727
+ filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0);
4728
+ if (!filter_buf) return stbi__err("outofmem", "Out of memory");
4729
+
4730
+ // Filtering for low-bit-depth images
4731
+ if (depth < 8) {
4732
+ filter_bytes = 1;
4733
+ width = img_width_bytes;
4734
+ }
4735
+
4676
4736
  for (j=0; j < y; ++j) {
4677
- stbi_uc *cur = a->out + stride*j;
4678
- stbi_uc *prior;
4737
+ // cur/prior filter buffers alternate
4738
+ stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes;
4739
+ stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes;
4740
+ stbi_uc *dest = a->out + stride*j;
4741
+ int nk = width * filter_bytes;
4679
4742
  int filter = *raw++;
4680
4743
 
4681
- if (filter > 4)
4682
- return stbi__err("invalid filter","Corrupt PNG");
4683
-
4684
- if (depth < 8) {
4685
- if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
4686
- cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
4687
- filter_bytes = 1;
4688
- width = img_width_bytes;
4744
+ // check filter type
4745
+ if (filter > 4) {
4746
+ all_ok = stbi__err("invalid filter","Corrupt PNG");
4747
+ break;
4689
4748
  }
4690
- prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
4691
4749
 
4692
4750
  // if first row, use special filter that doesn't sample previous row
4693
4751
  if (j == 0) filter = first_row_filter[filter];
4694
4752
 
4695
- // handle first byte explicitly
4696
- for (k=0; k < filter_bytes; ++k) {
4697
- switch (filter) {
4698
- case STBI__F_none : cur[k] = raw[k]; break;
4699
- case STBI__F_sub : cur[k] = raw[k]; break;
4700
- case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
4701
- case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
4702
- case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
4703
- case STBI__F_avg_first : cur[k] = raw[k]; break;
4704
- case STBI__F_paeth_first: cur[k] = raw[k]; break;
4705
- }
4706
- }
4707
-
4708
- if (depth == 8) {
4709
- if (img_n != out_n)
4710
- cur[img_n] = 255; // first pixel
4711
- raw += img_n;
4712
- cur += out_n;
4713
- prior += out_n;
4714
- } else if (depth == 16) {
4715
- if (img_n != out_n) {
4716
- cur[filter_bytes] = 255; // first pixel top byte
4717
- cur[filter_bytes+1] = 255; // first pixel bottom byte
4718
- }
4719
- raw += filter_bytes;
4720
- cur += output_bytes;
4721
- prior += output_bytes;
4722
- } else {
4723
- raw += 1;
4724
- cur += 1;
4725
- prior += 1;
4753
+ // perform actual filtering
4754
+ switch (filter) {
4755
+ case STBI__F_none:
4756
+ memcpy(cur, raw, nk);
4757
+ break;
4758
+ case STBI__F_sub:
4759
+ memcpy(cur, raw, filter_bytes);
4760
+ for (k = filter_bytes; k < nk; ++k)
4761
+ cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);
4762
+ break;
4763
+ case STBI__F_up:
4764
+ for (k = 0; k < nk; ++k)
4765
+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
4766
+ break;
4767
+ case STBI__F_avg:
4768
+ for (k = 0; k < filter_bytes; ++k)
4769
+ cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1));
4770
+ for (k = filter_bytes; k < nk; ++k)
4771
+ cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1));
4772
+ break;
4773
+ case STBI__F_paeth:
4774
+ for (k = 0; k < filter_bytes; ++k)
4775
+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)
4776
+ for (k = filter_bytes; k < nk; ++k)
4777
+ cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes]));
4778
+ break;
4779
+ case STBI__F_avg_first:
4780
+ memcpy(cur, raw, filter_bytes);
4781
+ for (k = filter_bytes; k < nk; ++k)
4782
+ cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1));
4783
+ break;
4726
4784
  }
4727
4785
 
4728
- // this is a little gross, so that we don't switch per-pixel or per-component
4729
- if (depth < 8 || img_n == out_n) {
4730
- int nk = (width - 1)*filter_bytes;
4731
- #define STBI__CASE(f) \
4732
- case f: \
4733
- for (k=0; k < nk; ++k)
4734
- switch (filter) {
4735
- // "none" filter turns into a memcpy here; make that explicit.
4736
- case STBI__F_none: memcpy(cur, raw, nk); break;
4737
- STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
4738
- STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
4739
- STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
4740
- STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
4741
- STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
4742
- STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
4743
- }
4744
- #undef STBI__CASE
4745
- raw += nk;
4746
- } else {
4747
- STBI_ASSERT(img_n+1 == out_n);
4748
- #define STBI__CASE(f) \
4749
- case f: \
4750
- for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
4751
- for (k=0; k < filter_bytes; ++k)
4752
- switch (filter) {
4753
- STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
4754
- STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
4755
- STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
4756
- STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
4757
- STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
4758
- STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
4759
- STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
4760
- }
4761
- #undef STBI__CASE
4762
-
4763
- // the loop above sets the high byte of the pixels' alpha, but for
4764
- // 16 bit png files we also need the low byte set. we'll do that here.
4765
- if (depth == 16) {
4766
- cur = a->out + stride*j; // start at the beginning of the row again
4767
- for (i=0; i < x; ++i,cur+=output_bytes) {
4768
- cur[filter_bytes+1] = 255;
4769
- }
4770
- }
4771
- }
4772
- }
4786
+ raw += nk;
4773
4787
 
4774
- // we make a separate pass to expand bits to pixels; for performance,
4775
- // this could run two scanlines behind the above code, so it won't
4776
- // intefere with filtering but will still be in the cache.
4777
- if (depth < 8) {
4778
- for (j=0; j < y; ++j) {
4779
- stbi_uc *cur = a->out + stride*j;
4780
- stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes;
4781
- // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
4782
- // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
4788
+ // expand decoded bits in cur to dest, also adding an extra alpha channel if desired
4789
+ if (depth < 8) {
4783
4790
  stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
4791
+ stbi_uc *in = cur;
4792
+ stbi_uc *out = dest;
4793
+ stbi_uc inb = 0;
4794
+ stbi__uint32 nsmp = x*img_n;
4784
4795
 
4785
- // note that the final byte might overshoot and write more data than desired.
4786
- // we can allocate enough data that this never writes out of memory, but it
4787
- // could also overwrite the next scanline. can it overwrite non-empty data
4788
- // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
4789
- // so we need to explicitly clamp the final ones
4790
-
4796
+ // expand bits to bytes first
4791
4797
  if (depth == 4) {
4792
- for (k=x*img_n; k >= 2; k-=2, ++in) {
4793
- *cur++ = scale * ((*in >> 4) );
4794
- *cur++ = scale * ((*in ) & 0x0f);
4798
+ for (i=0; i < nsmp; ++i) {
4799
+ if ((i & 1) == 0) inb = *in++;
4800
+ *out++ = scale * (inb >> 4);
4801
+ inb <<= 4;
4795
4802
  }
4796
- if (k > 0) *cur++ = scale * ((*in >> 4) );
4797
4803
  } else if (depth == 2) {
4798
- for (k=x*img_n; k >= 4; k-=4, ++in) {
4799
- *cur++ = scale * ((*in >> 6) );
4800
- *cur++ = scale * ((*in >> 4) & 0x03);
4801
- *cur++ = scale * ((*in >> 2) & 0x03);
4802
- *cur++ = scale * ((*in ) & 0x03);
4804
+ for (i=0; i < nsmp; ++i) {
4805
+ if ((i & 3) == 0) inb = *in++;
4806
+ *out++ = scale * (inb >> 6);
4807
+ inb <<= 2;
4803
4808
  }
4804
- if (k > 0) *cur++ = scale * ((*in >> 6) );
4805
- if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
4806
- if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
4807
- } else if (depth == 1) {
4808
- for (k=x*img_n; k >= 8; k-=8, ++in) {
4809
- *cur++ = scale * ((*in >> 7) );
4810
- *cur++ = scale * ((*in >> 6) & 0x01);
4811
- *cur++ = scale * ((*in >> 5) & 0x01);
4812
- *cur++ = scale * ((*in >> 4) & 0x01);
4813
- *cur++ = scale * ((*in >> 3) & 0x01);
4814
- *cur++ = scale * ((*in >> 2) & 0x01);
4815
- *cur++ = scale * ((*in >> 1) & 0x01);
4816
- *cur++ = scale * ((*in ) & 0x01);
4809
+ } else {
4810
+ STBI_ASSERT(depth == 1);
4811
+ for (i=0; i < nsmp; ++i) {
4812
+ if ((i & 7) == 0) inb = *in++;
4813
+ *out++ = scale * (inb >> 7);
4814
+ inb <<= 1;
4817
4815
  }
4818
- if (k > 0) *cur++ = scale * ((*in >> 7) );
4819
- if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
4820
- if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
4821
- if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
4822
- if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
4823
- if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
4824
- if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
4825
4816
  }
4826
- if (img_n != out_n) {
4827
- int q;
4828
- // insert alpha = 255
4829
- cur = a->out + stride*j;
4817
+
4818
+ // insert alpha=255 values if desired
4819
+ if (img_n != out_n)
4820
+ stbi__create_png_alpha_expand8(dest, dest, x, img_n);
4821
+ } else if (depth == 8) {
4822
+ if (img_n == out_n)
4823
+ memcpy(dest, cur, x*img_n);
4824
+ else
4825
+ stbi__create_png_alpha_expand8(dest, cur, x, img_n);
4826
+ } else if (depth == 16) {
4827
+ // convert the image data from big-endian to platform-native
4828
+ stbi__uint16 *dest16 = (stbi__uint16*)dest;
4829
+ stbi__uint32 nsmp = x*img_n;
4830
+
4831
+ if (img_n == out_n) {
4832
+ for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
4833
+ *dest16 = (cur[0] << 8) | cur[1];
4834
+ } else {
4835
+ STBI_ASSERT(img_n+1 == out_n);
4830
4836
  if (img_n == 1) {
4831
- for (q=x-1; q >= 0; --q) {
4832
- cur[q*2+1] = 255;
4833
- cur[q*2+0] = cur[q];
4837
+ for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
4838
+ dest16[0] = (cur[0] << 8) | cur[1];
4839
+ dest16[1] = 0xffff;
4834
4840
  }
4835
4841
  } else {
4836
4842
  STBI_ASSERT(img_n == 3);
4837
- for (q=x-1; q >= 0; --q) {
4838
- cur[q*4+3] = 255;
4839
- cur[q*4+2] = cur[q*3+2];
4840
- cur[q*4+1] = cur[q*3+1];
4841
- cur[q*4+0] = cur[q*3+0];
4843
+ for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
4844
+ dest16[0] = (cur[0] << 8) | cur[1];
4845
+ dest16[1] = (cur[2] << 8) | cur[3];
4846
+ dest16[2] = (cur[4] << 8) | cur[5];
4847
+ dest16[3] = 0xffff;
4842
4848
  }
4843
4849
  }
4844
4850
  }
4845
4851
  }
4846
- } else if (depth == 16) {
4847
- // force the image data from big-endian to platform-native.
4848
- // this is done in a separate pass due to the decoding relying
4849
- // on the data being untouched, but could probably be done
4850
- // per-line during decode if care is taken.
4851
- stbi_uc *cur = a->out;
4852
- stbi__uint16 *cur16 = (stbi__uint16*)cur;
4853
-
4854
- for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
4855
- *cur16 = (cur[0] << 8) | cur[1];
4856
- }
4857
4852
  }
4858
4853
 
4854
+ STBI_FREE(filter_buf);
4855
+ if (!all_ok) return 0;
4856
+
4859
4857
  return 1;
4860
4858
  }
4861
4859
 
@@ -213,6 +213,7 @@ Gosu_IF_TILEABLE_TOP
213
213
  Gosu_Image_create
214
214
  Gosu_Image_create_from_blob
215
215
  Gosu_Image_create_from_markup
216
+ Gosu_Image_create_from_rect
216
217
  Gosu_Image_create_from_subimage
217
218
  Gosu_Image_create_from_text
218
219
  Gosu_Image_create_from_tiles
@@ -26,7 +26,7 @@ auto Gosu_translate_exceptions(Functor functor)
26
26
  }
27
27
  }
28
28
 
29
- // C-compatible wrapper structs for Gosu classes
29
+ // C-compatible wrapper structs for Gosu classes. (No inheritance because of missing virtual dtors.)
30
30
 
31
31
  struct Gosu_Channel
32
32
  {
@@ -48,7 +48,7 @@ struct Gosu_Sample
48
48
  Gosu::Sample sample;
49
49
  };
50
50
 
51
- // Use inheritance where composition is not feasible
51
+ // Use inheritance where composition is not feasible (because we want to compare pointers).
52
52
 
53
53
  struct Gosu_Song : Gosu::Song
54
54
  {
data/ffi/Gosu_Image.cpp CHANGED
@@ -2,9 +2,18 @@
2
2
  #include <cstring> // for std::memcpy
3
3
 
4
4
  GOSU_FFI_API Gosu_Image* Gosu_Image_create(const char* filename, unsigned image_flags)
5
+ {
6
+ return Gosu_translate_exceptions([=] { //
7
+ return new Gosu_Image { Gosu::Image(filename, image_flags) };
8
+ });
9
+ }
10
+
11
+ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_rect(const char* filename, //
12
+ int x, int y, int width, int height,
13
+ unsigned image_flags)
5
14
  {
6
15
  return Gosu_translate_exceptions([=] {
7
- return new Gosu_Image{Gosu::Image{filename, image_flags}};
16
+ return new Gosu_Image { Gosu::Image(filename, { x, y, width, height }, image_flags) };
8
17
  });
9
18
  }
10
19
 
@@ -32,32 +41,35 @@ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_text(const char* text, const cha
32
41
  });
33
42
  }
34
43
 
35
- GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, int byte_count, int columns,
36
- int rows, unsigned image_flags)
44
+ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, size_t byte_count, //
45
+ int columns, int rows, //
46
+ int x, int y, int width, int height,
47
+ unsigned image_flags)
37
48
  {
38
49
  return Gosu_translate_exceptions([=] {
39
- std::size_t size = columns * rows * 4;
40
- Gosu::Bitmap bitmap{columns, rows};
50
+ const int pixels = columns * rows * 4;
51
+ Gosu::Bitmap bitmap;
41
52
 
42
- if (byte_count == size) {
53
+ if (byte_count == pixels) {
43
54
  // 32 bit per pixel, assume R8G8B8A8
44
- std::memcpy(bitmap.data(), blob, size);
55
+ bitmap = Gosu::Bitmap(columns, rows, Gosu::Buffer(blob, byte_count, nullptr));
45
56
  }
46
- else if (byte_count == size * sizeof(float)) {
47
- // 128 bit per channel, assume float/float/float/float - for Texplay compatibility.
57
+ else if (byte_count == pixels * 4UL * sizeof(float)) {
58
+ bitmap.resize(columns, rows);
59
+ // 128 bit per channel, assume float/float/float/float RGBA - for Texplay compatibility.
48
60
  const float* in = static_cast<const float*>(blob);
49
61
  Gosu::Color::Channel* out = reinterpret_cast<Gosu::Color::Channel*>(bitmap.data());
50
- for (std::size_t i = 0; i < size; ++i) {
62
+ for (std::size_t i = 0; i < pixels; ++i) {
51
63
  out[i] = static_cast<Gosu::Color::Channel>(in[i] * 255);
52
64
  }
53
65
  }
54
66
  else {
55
- throw std::invalid_argument{"Invalid byte_count " + std::to_string(byte_count) +
56
- "for image of size " + std::to_string(columns) + "x" +
57
- std::to_string(rows)};
67
+ throw std::invalid_argument("Invalid byte_count " + std::to_string(byte_count)
68
+ + " for image of size " + std::to_string(columns) + "x"
69
+ + std::to_string(rows));
58
70
  }
59
71
 
60
- return new Gosu_Image{Gosu::Image{bitmap, image_flags}};
72
+ return new Gosu_Image { Gosu::Image(bitmap, { x, y, width, height }, image_flags) };
61
73
  });
62
74
  }
63
75
 
data/ffi/Gosu_Image.h CHANGED
@@ -1,6 +1,7 @@
1
1
  #pragma once
2
2
 
3
3
  #include "Gosu_FFI.h"
4
+ #include <stddef.h> // for size_t
4
5
  #include <stdint.h>
5
6
 
6
7
  typedef struct Gosu_Image Gosu_Image;
@@ -13,8 +14,13 @@ typedef struct Gosu_GLTexInfo
13
14
 
14
15
  // Constructor
15
16
  GOSU_FFI_API Gosu_Image* Gosu_Image_create(const char* filename, unsigned image_flags);
16
- GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, int byte_count, int width,
17
- int height, unsigned image_flags);
17
+ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_rect(const char* filename, //
18
+ int x, int y, int width, int height,
19
+ unsigned image_flags);
20
+ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, size_t byte_count, //
21
+ int columns, int rows, //
22
+ int x, int y, int width, int height,
23
+ unsigned image_flags);
18
24
  GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_markup(const char* markup, const char* font,
19
25
  double font_height, int width,
20
26
  double spacing, unsigned align,
@@ -24,7 +24,7 @@ namespace Gosu
24
24
  /// For more flexibility, use the corresponding constructor that uses a Bitmap object.
25
25
  explicit Image(const std::string& filename, unsigned image_flags = IF_SMOOTH);
26
26
 
27
- //! Loads a portion of the the image at the given filename..
27
+ /// Loads a portion of the the image at the given filename..
28
28
  ///
29
29
  /// A color key of #ff00ff is automatically applied to BMP image files.
30
30
  /// For more flexibility, use the corresponding constructor that uses a Bitmap object.
data/lib/SDL2.dll CHANGED
Binary file
data/lib/gosu/ffi.rb CHANGED
@@ -134,11 +134,12 @@ module GosuFFI
134
134
  attach_function :Gosu_Font_set_image, [:pointer, :string, :uint32, :pointer], :void
135
135
 
136
136
  attach_function :Gosu_Image_create, [:string, :uint32], :pointer
137
+ attach_function :Gosu_Image_create_from_rect, [:string, :int, :int, :int, :int, :uint32], :pointer
137
138
  attach_function :Gosu_Image_destroy, [:pointer], :void
138
139
 
139
140
  attach_function :Gosu_Image_create_from_markup, [:string, :string, :double, :int, :double, :uint32, :uint32, :uint32], :pointer
140
141
  attach_function :Gosu_Image_create_from_text, [:string, :string, :double, :int, :double, :uint32, :uint32, :uint32], :pointer
141
- attach_function :Gosu_Image_create_from_blob, [:pointer, :ulong, :int, :int, :uint32], :pointer
142
+ attach_function :Gosu_Image_create_from_blob, [:pointer, :size_t, :int, :int, :int, :int, :int, :int, :uint32], :pointer
142
143
  attach_function :Gosu_Image_create_from_subimage, [:pointer, :int, :int, :int, :int], :pointer
143
144
  attach_function :Gosu_Image_create_from_tiles, [:string, :int, :int, :_callback_with_image, :pointer, :uint32], :void
144
145
  attach_function :Gosu_Image_create_tiles_from_image, [:pointer, :int, :int, :_callback_with_image, :pointer, :uint32], :void